clang 15.0.7
SemaOpenMP.cpp
Go to the documentation of this file.
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
14#include "TreeTransform.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclCXX.h"
22#include "clang/AST/StmtCXX.h"
31#include "clang/Sema/Lookup.h"
32#include "clang/Sema/Scope.h"
35#include "llvm/ADT/IndexedMap.h"
36#include "llvm/ADT/PointerEmbeddedInt.h"
37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/SmallSet.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/Frontend/OpenMP/OMPAssume.h"
41#include "llvm/Frontend/OpenMP/OMPConstants.h"
42#include <set>
43
44using namespace clang;
45using namespace llvm::omp;
46
47//===----------------------------------------------------------------------===//
48// Stack of data-sharing attributes for variables
49//===----------------------------------------------------------------------===//
50
52 Sema &SemaRef, Expr *E,
54 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
55
56namespace {
57/// Default data sharing attributes, which can be applied to directive.
58enum DefaultDataSharingAttributes {
59 DSA_unspecified = 0, /// Data sharing attribute not specified.
60 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
61 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
62 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
63 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
64};
65
66/// Stack for tracking declarations used in OpenMP directives and
67/// clauses and their data-sharing attributes.
68class DSAStackTy {
69public:
70 struct DSAVarData {
71 OpenMPDirectiveKind DKind = OMPD_unknown;
72 OpenMPClauseKind CKind = OMPC_unknown;
73 unsigned Modifier = 0;
74 const Expr *RefExpr = nullptr;
75 DeclRefExpr *PrivateCopy = nullptr;
76 SourceLocation ImplicitDSALoc;
77 bool AppliedToPointee = false;
78 DSAVarData() = default;
79 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
80 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
81 SourceLocation ImplicitDSALoc, unsigned Modifier,
82 bool AppliedToPointee)
83 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
84 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
85 AppliedToPointee(AppliedToPointee) {}
86 };
87 using OperatorOffsetTy =
89 using DoacrossDependMapTy =
90 llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
91 /// Kind of the declaration used in the uses_allocators clauses.
92 enum class UsesAllocatorsDeclKind {
93 /// Predefined allocator
94 PredefinedAllocator,
95 /// User-defined allocator
96 UserDefinedAllocator,
97 /// The declaration that represent allocator trait
98 AllocatorTrait,
99 };
100
101private:
102 struct DSAInfo {
103 OpenMPClauseKind Attributes = OMPC_unknown;
104 unsigned Modifier = 0;
105 /// Pointer to a reference expression and a flag which shows that the
106 /// variable is marked as lastprivate(true) or not (false).
107 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
108 DeclRefExpr *PrivateCopy = nullptr;
109 /// true if the attribute is applied to the pointee, not the variable
110 /// itself.
111 bool AppliedToPointee = false;
112 };
113 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
114 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
115 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
116 using LoopControlVariablesMapTy =
117 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
118 /// Struct that associates a component with the clause kind where they are
119 /// found.
120 struct MappedExprComponentTy {
122 OpenMPClauseKind Kind = OMPC_unknown;
123 };
124 using MappedExprComponentsTy =
125 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
126 using CriticalsWithHintsTy =
127 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
128 struct ReductionData {
129 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
130 SourceRange ReductionRange;
131 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
132 ReductionData() = default;
133 void set(BinaryOperatorKind BO, SourceRange RR) {
134 ReductionRange = RR;
135 ReductionOp = BO;
136 }
137 void set(const Expr *RefExpr, SourceRange RR) {
138 ReductionRange = RR;
139 ReductionOp = RefExpr;
140 }
141 };
142 using DeclReductionMapTy =
143 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
144 struct DefaultmapInfo {
145 OpenMPDefaultmapClauseModifier ImplicitBehavior =
147 SourceLocation SLoc;
148 DefaultmapInfo() = default;
150 : ImplicitBehavior(M), SLoc(Loc) {}
151 };
152
153 struct SharingMapTy {
154 DeclSAMapTy SharingMap;
155 DeclReductionMapTy ReductionMap;
156 UsedRefMapTy AlignedMap;
157 UsedRefMapTy NontemporalMap;
158 MappedExprComponentsTy MappedExprComponents;
159 LoopControlVariablesMapTy LCVMap;
160 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
161 SourceLocation DefaultAttrLoc;
162 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown];
163 OpenMPDirectiveKind Directive = OMPD_unknown;
164 DeclarationNameInfo DirectiveName;
165 Scope *CurScope = nullptr;
166 DeclContext *Context = nullptr;
167 SourceLocation ConstructLoc;
168 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
169 /// get the data (loop counters etc.) about enclosing loop-based construct.
170 /// This data is required during codegen.
171 DoacrossDependMapTy DoacrossDepends;
172 /// First argument (Expr *) contains optional argument of the
173 /// 'ordered' clause, the second one is true if the regions has 'ordered'
174 /// clause, false otherwise.
176 unsigned AssociatedLoops = 1;
177 bool HasMutipleLoops = false;
178 const Decl *PossiblyLoopCounter = nullptr;
179 bool NowaitRegion = false;
180 bool UntiedRegion = false;
181 bool CancelRegion = false;
182 bool LoopStart = false;
183 bool BodyComplete = false;
184 SourceLocation PrevScanLocation;
185 SourceLocation PrevOrderedLocation;
186 SourceLocation InnerTeamsRegionLoc;
187 /// Reference to the taskgroup task_reduction reference expression.
188 Expr *TaskgroupReductionRef = nullptr;
189 llvm::DenseSet<QualType> MappedClassesQualTypes;
190 SmallVector<Expr *, 4> InnerUsedAllocators;
191 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
192 /// List of globals marked as declare target link in this target region
193 /// (isOpenMPTargetExecutionDirective(Directive) == true).
194 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
195 /// List of decls used in inclusive/exclusive clauses of the scan directive.
196 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
197 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
198 UsesAllocatorsDecls;
199 /// Data is required on creating capture fields for implicit
200 /// default first|private clause.
201 struct ImplicitDefaultFDInfoTy {
202 /// Field decl.
203 const FieldDecl *FD = nullptr;
204 /// Nesting stack level
205 size_t StackLevel = 0;
206 /// Capture variable decl.
207 VarDecl *VD = nullptr;
208 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
209 VarDecl *VD)
210 : FD(FD), StackLevel(StackLevel), VD(VD) {}
211 };
212 /// List of captured fields
214 ImplicitDefaultFirstprivateFDs;
215 Expr *DeclareMapperVar = nullptr;
216 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
217 Scope *CurScope, SourceLocation Loc)
218 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
219 ConstructLoc(Loc) {}
220 SharingMapTy() = default;
221 };
222
223 using StackTy = SmallVector<SharingMapTy, 4>;
224
225 /// Stack of used declaration and their data-sharing attributes.
226 DeclSAMapTy Threadprivates;
227 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
229 /// true, if check for DSA must be from parent directive, false, if
230 /// from current directive.
231 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
232 Sema &SemaRef;
233 bool ForceCapturing = false;
234 /// true if all the variables in the target executable directives must be
235 /// captured by reference.
236 bool ForceCaptureByReferenceInTargetExecutable = false;
237 CriticalsWithHintsTy Criticals;
238 unsigned IgnoredStackElements = 0;
239
240 /// Iterators over the stack iterate in order from innermost to outermost
241 /// directive.
242 using const_iterator = StackTy::const_reverse_iterator;
243 const_iterator begin() const {
244 return Stack.empty() ? const_iterator()
245 : Stack.back().first.rbegin() + IgnoredStackElements;
246 }
247 const_iterator end() const {
248 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
249 }
250 using iterator = StackTy::reverse_iterator;
251 iterator begin() {
252 return Stack.empty() ? iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
254 }
255 iterator end() {
256 return Stack.empty() ? iterator() : Stack.back().first.rend();
257 }
258
259 // Convenience operations to get at the elements of the stack.
260
261 bool isStackEmpty() const {
262 return Stack.empty() ||
263 Stack.back().second != CurrentNonCapturingFunctionScope ||
264 Stack.back().first.size() <= IgnoredStackElements;
265 }
266 size_t getStackSize() const {
267 return isStackEmpty() ? 0
268 : Stack.back().first.size() - IgnoredStackElements;
269 }
270
271 SharingMapTy *getTopOfStackOrNull() {
272 size_t Size = getStackSize();
273 if (Size == 0)
274 return nullptr;
275 return &Stack.back().first[Size - 1];
276 }
277 const SharingMapTy *getTopOfStackOrNull() const {
278 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
279 }
280 SharingMapTy &getTopOfStack() {
281 assert(!isStackEmpty() && "no current directive");
282 return *getTopOfStackOrNull();
283 }
284 const SharingMapTy &getTopOfStack() const {
285 return const_cast<DSAStackTy &>(*this).getTopOfStack();
286 }
287
288 SharingMapTy *getSecondOnStackOrNull() {
289 size_t Size = getStackSize();
290 if (Size <= 1)
291 return nullptr;
292 return &Stack.back().first[Size - 2];
293 }
294 const SharingMapTy *getSecondOnStackOrNull() const {
295 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
296 }
297
298 /// Get the stack element at a certain level (previously returned by
299 /// \c getNestingLevel).
300 ///
301 /// Note that nesting levels count from outermost to innermost, and this is
302 /// the reverse of our iteration order where new inner levels are pushed at
303 /// the front of the stack.
304 SharingMapTy &getStackElemAtLevel(unsigned Level) {
305 assert(Level < getStackSize() && "no such stack element");
306 return Stack.back().first[Level];
307 }
308 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
309 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
310 }
311
312 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
313
314 /// Checks if the variable is a local for OpenMP region.
315 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
316
317 /// Vector of previously declared requires directives
319 /// omp_allocator_handle_t type.
320 QualType OMPAllocatorHandleT;
321 /// omp_depend_t type.
322 QualType OMPDependT;
323 /// omp_event_handle_t type.
324 QualType OMPEventHandleT;
325 /// omp_alloctrait_t type.
326 QualType OMPAlloctraitT;
327 /// Expression for the predefined allocators.
328 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
329 nullptr};
330 /// Vector of previously encountered target directives
331 SmallVector<SourceLocation, 2> TargetLocations;
332 SourceLocation AtomicLocation;
333 /// Vector of declare variant construct traits.
335
336public:
337 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
338
339 /// Sets omp_allocator_handle_t type.
340 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
341 /// Gets omp_allocator_handle_t type.
342 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
343 /// Sets omp_alloctrait_t type.
344 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
345 /// Gets omp_alloctrait_t type.
346 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
347 /// Sets the given default allocator.
348 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
349 Expr *Allocator) {
350 OMPPredefinedAllocators[AllocatorKind] = Allocator;
351 }
352 /// Returns the specified default allocator.
353 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
354 return OMPPredefinedAllocators[AllocatorKind];
355 }
356 /// Sets omp_depend_t type.
357 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
358 /// Gets omp_depend_t type.
359 QualType getOMPDependT() const { return OMPDependT; }
360
361 /// Sets omp_event_handle_t type.
362 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
363 /// Gets omp_event_handle_t type.
364 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
365
366 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
367 OpenMPClauseKind getClauseParsingMode() const {
368 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
369 return ClauseKindMode;
370 }
371 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
372
373 bool isBodyComplete() const {
374 const SharingMapTy *Top = getTopOfStackOrNull();
375 return Top && Top->BodyComplete;
376 }
377 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
378
379 bool isForceVarCapturing() const { return ForceCapturing; }
380 void setForceVarCapturing(bool V) { ForceCapturing = V; }
381
382 void setForceCaptureByReferenceInTargetExecutable(bool V) {
383 ForceCaptureByReferenceInTargetExecutable = V;
384 }
385 bool isForceCaptureByReferenceInTargetExecutable() const {
386 return ForceCaptureByReferenceInTargetExecutable;
387 }
388
389 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
390 Scope *CurScope, SourceLocation Loc) {
391 assert(!IgnoredStackElements &&
392 "cannot change stack while ignoring elements");
393 if (Stack.empty() ||
394 Stack.back().second != CurrentNonCapturingFunctionScope)
395 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
396 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
397 Stack.back().first.back().DefaultAttrLoc = Loc;
398 }
399
400 void pop() {
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
403 assert(!Stack.back().first.empty() &&
404 "Data-sharing attributes stack is empty!");
405 Stack.back().first.pop_back();
406 }
407
408 /// RAII object to temporarily leave the scope of a directive when we want to
409 /// logically operate in its parent.
410 class ParentDirectiveScope {
411 DSAStackTy &Self;
412 bool Active;
413
414 public:
415 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
416 : Self(Self), Active(false) {
417 if (Activate)
418 enable();
419 }
420 ~ParentDirectiveScope() { disable(); }
421 void disable() {
422 if (Active) {
423 --Self.IgnoredStackElements;
424 Active = false;
425 }
426 }
427 void enable() {
428 if (!Active) {
429 ++Self.IgnoredStackElements;
430 Active = true;
431 }
432 }
433 };
434
435 /// Marks that we're started loop parsing.
436 void loopInit() {
437 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
438 "Expected loop-based directive.");
439 getTopOfStack().LoopStart = true;
440 }
441 /// Start capturing of the variables in the loop context.
442 void loopStart() {
443 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
444 "Expected loop-based directive.");
445 getTopOfStack().LoopStart = false;
446 }
447 /// true, if variables are captured, false otherwise.
448 bool isLoopStarted() const {
449 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
450 "Expected loop-based directive.");
451 return !getTopOfStack().LoopStart;
452 }
453 /// Marks (or clears) declaration as possibly loop counter.
454 void resetPossibleLoopCounter(const Decl *D = nullptr) {
455 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
456 }
457 /// Gets the possible loop counter decl.
458 const Decl *getPossiblyLoopCunter() const {
459 return getTopOfStack().PossiblyLoopCounter;
460 }
461 /// Start new OpenMP region stack in new non-capturing function.
462 void pushFunction() {
463 assert(!IgnoredStackElements &&
464 "cannot change stack while ignoring elements");
465 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
466 assert(!isa<CapturingScopeInfo>(CurFnScope));
467 CurrentNonCapturingFunctionScope = CurFnScope;
468 }
469 /// Pop region stack for non-capturing function.
470 void popFunction(const FunctionScopeInfo *OldFSI) {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 if (!Stack.empty() && Stack.back().second == OldFSI) {
474 assert(Stack.back().first.empty());
475 Stack.pop_back();
476 }
477 CurrentNonCapturingFunctionScope = nullptr;
478 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
479 if (!isa<CapturingScopeInfo>(FSI)) {
480 CurrentNonCapturingFunctionScope = FSI;
481 break;
482 }
483 }
484 }
485
486 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
487 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
488 }
489 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
490 getCriticalWithHint(const DeclarationNameInfo &Name) const {
491 auto I = Criticals.find(Name.getAsString());
492 if (I != Criticals.end())
493 return I->second;
494 return std::make_pair(nullptr, llvm::APSInt());
495 }
496 /// If 'aligned' declaration for given variable \a D was not seen yet,
497 /// add it and return NULL; otherwise return previous occurrence's expression
498 /// for diagnostics.
499 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
500 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
501 /// add it and return NULL; otherwise return previous occurrence's expression
502 /// for diagnostics.
503 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
504
505 /// Register specified variable as loop control variable.
506 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
507 /// Check if the specified variable is a loop control variable for
508 /// current region.
509 /// \return The index of the loop control variable in the list of associated
510 /// for-loops (from outer to inner).
511 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
512 /// Check if the specified variable is a loop control variable for
513 /// parent region.
514 /// \return The index of the loop control variable in the list of associated
515 /// for-loops (from outer to inner).
516 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
522 unsigned Level) const;
523 /// Get the loop control variable for the I-th loop (or nullptr) in
524 /// parent directive.
525 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
526
527 /// Marks the specified decl \p D as used in scan directive.
528 void markDeclAsUsedInScanDirective(ValueDecl *D) {
529 if (SharingMapTy *Stack = getSecondOnStackOrNull())
530 Stack->UsedInScanDirective.insert(D);
531 }
532
533 /// Checks if the specified declaration was used in the inner scan directive.
534 bool isUsedInScanDirective(ValueDecl *D) const {
535 if (const SharingMapTy *Stack = getTopOfStackOrNull())
536 return Stack->UsedInScanDirective.contains(D);
537 return false;
538 }
539
540 /// Adds explicit data sharing attribute to the specified declaration.
541 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
542 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
543 bool AppliedToPointee = false);
544
545 /// Adds additional information for the reduction items with the reduction id
546 /// represented as an operator.
547 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
549 /// Adds additional information for the reduction items with the reduction id
550 /// represented as reduction identifier.
551 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
552 const Expr *ReductionRef);
553 /// Returns the location and reduction operation from the innermost parent
554 /// region for the given \p D.
555 const DSAVarData
556 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
558 Expr *&TaskgroupDescriptor) const;
559 /// Returns the location and reduction operation from the innermost parent
560 /// region for the given \p D.
561 const DSAVarData
562 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
563 const Expr *&ReductionRef,
564 Expr *&TaskgroupDescriptor) const;
565 /// Return reduction reference expression for the current taskgroup or
566 /// parallel/worksharing directives with task reductions.
567 Expr *getTaskgroupReductionRef() const {
568 assert((getTopOfStack().Directive == OMPD_taskgroup ||
569 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
570 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
571 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
572 "taskgroup reference expression requested for non taskgroup or "
573 "parallel/worksharing directive.");
574 return getTopOfStack().TaskgroupReductionRef;
575 }
576 /// Checks if the given \p VD declaration is actually a taskgroup reduction
577 /// descriptor variable at the \p Level of OpenMP regions.
578 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
579 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
580 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
581 ->getDecl() == VD;
582 }
583
584 /// Returns data sharing attributes from top of the stack for the
585 /// specified declaration.
586 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
587 /// Returns data-sharing attributes for the specified declaration.
588 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
589 /// Returns data-sharing attributes for the specified declaration.
590 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
591 /// Checks if the specified variables has data-sharing attributes which
592 /// match specified \a CPred predicate in any directive which matches \a DPred
593 /// predicate.
594 const DSAVarData
595 hasDSA(ValueDecl *D,
596 const llvm::function_ref<bool(OpenMPClauseKind, bool,
597 DefaultDataSharingAttributes)>
598 CPred,
599 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
600 bool FromParent) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any innermost directive which
603 /// matches \a DPred predicate.
604 const DSAVarData
605 hasInnermostDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has explicit data-sharing
610 /// attributes which match specified \a CPred predicate at the specified
611 /// OpenMP region.
612 bool
613 hasExplicitDSA(const ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 unsigned Level, bool NotLastprivate = false) const;
616
617 /// Returns true if the directive at level \Level matches in the
618 /// specified \a DPred predicate.
619 bool hasExplicitDirective(
620 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
621 unsigned Level) const;
622
623 /// Finds a directive which matches specified \a DPred predicate.
624 bool hasDirective(
625 const llvm::function_ref<bool(
627 DPred,
628 bool FromParent) const;
629
630 /// Returns currently analyzed directive.
631 OpenMPDirectiveKind getCurrentDirective() const {
632 const SharingMapTy *Top = getTopOfStackOrNull();
633 return Top ? Top->Directive : OMPD_unknown;
634 }
635 /// Returns directive kind at specified level.
636 OpenMPDirectiveKind getDirective(unsigned Level) const {
637 assert(!isStackEmpty() && "No directive at specified level.");
638 return getStackElemAtLevel(Level).Directive;
639 }
640 /// Returns the capture region at the specified level.
641 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
642 unsigned OpenMPCaptureLevel) const {
644 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
645 return CaptureRegions[OpenMPCaptureLevel];
646 }
647 /// Returns parent directive.
648 OpenMPDirectiveKind getParentDirective() const {
649 const SharingMapTy *Parent = getSecondOnStackOrNull();
650 return Parent ? Parent->Directive : OMPD_unknown;
651 }
652
653 /// Add requires decl to internal vector
654 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
655
656 /// Checks if the defined 'requires' directive has specified type of clause.
657 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
658 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
659 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
660 return isa<ClauseType>(C);
661 });
662 });
663 }
664
665 /// Checks for a duplicate clause amongst previously declared requires
666 /// directives
667 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
668 bool IsDuplicate = false;
669 for (OMPClause *CNew : ClauseList) {
670 for (const OMPRequiresDecl *D : RequiresDecls) {
671 for (const OMPClause *CPrev : D->clauselists()) {
672 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
673 SemaRef.Diag(CNew->getBeginLoc(),
674 diag::err_omp_requires_clause_redeclaration)
675 << getOpenMPClauseName(CNew->getClauseKind());
676 SemaRef.Diag(CPrev->getBeginLoc(),
677 diag::note_omp_requires_previous_clause)
678 << getOpenMPClauseName(CPrev->getClauseKind());
679 IsDuplicate = true;
680 }
681 }
682 }
683 }
684 return IsDuplicate;
685 }
686
687 /// Add location of previously encountered target to internal vector
688 void addTargetDirLocation(SourceLocation LocStart) {
689 TargetLocations.push_back(LocStart);
690 }
691
692 /// Add location for the first encountered atomicc directive.
693 void addAtomicDirectiveLoc(SourceLocation Loc) {
694 if (AtomicLocation.isInvalid())
695 AtomicLocation = Loc;
696 }
697
698 /// Returns the location of the first encountered atomic directive in the
699 /// module.
700 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
701
702 // Return previously encountered target region locations.
703 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
704 return TargetLocations;
705 }
706
707 /// Set default data sharing attribute to none.
708 void setDefaultDSANone(SourceLocation Loc) {
709 getTopOfStack().DefaultAttr = DSA_none;
710 getTopOfStack().DefaultAttrLoc = Loc;
711 }
712 /// Set default data sharing attribute to shared.
713 void setDefaultDSAShared(SourceLocation Loc) {
714 getTopOfStack().DefaultAttr = DSA_shared;
715 getTopOfStack().DefaultAttrLoc = Loc;
716 }
717 /// Set default data sharing attribute to private.
718 void setDefaultDSAPrivate(SourceLocation Loc) {
719 getTopOfStack().DefaultAttr = DSA_private;
720 getTopOfStack().DefaultAttrLoc = Loc;
721 }
722 /// Set default data sharing attribute to firstprivate.
723 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
724 getTopOfStack().DefaultAttr = DSA_firstprivate;
725 getTopOfStack().DefaultAttrLoc = Loc;
726 }
727 /// Set default data mapping attribute to Modifier:Kind
728 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
730 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
731 DMI.ImplicitBehavior = M;
732 DMI.SLoc = Loc;
733 }
734 /// Check whether the implicit-behavior has been set in defaultmap
735 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
736 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
737 return getTopOfStack()
738 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
739 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
740 getTopOfStack()
741 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
742 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
743 getTopOfStack()
744 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
745 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
746 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
748 }
749
750 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
751 return ConstructTraits;
752 }
753 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
754 bool ScopeEntry) {
755 if (ScopeEntry)
756 ConstructTraits.append(Traits.begin(), Traits.end());
757 else
758 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
759 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
760 assert(Top == Trait && "Something left a trait on the stack!");
761 (void)Trait;
762 (void)Top;
763 }
764 }
765
766 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
767 return getStackSize() <= Level ? DSA_unspecified
768 : getStackElemAtLevel(Level).DefaultAttr;
769 }
770 DefaultDataSharingAttributes getDefaultDSA() const {
771 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
772 }
773 SourceLocation getDefaultDSALocation() const {
774 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
775 }
777 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
778 return isStackEmpty()
780 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
781 }
783 getDefaultmapModifierAtLevel(unsigned Level,
784 OpenMPDefaultmapClauseKind Kind) const {
785 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
786 }
787 bool isDefaultmapCapturedByRef(unsigned Level,
788 OpenMPDefaultmapClauseKind Kind) const {
790 getDefaultmapModifierAtLevel(Level, Kind);
791 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
792 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
793 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
794 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
795 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
796 }
797 return true;
798 }
799 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
801 switch (Kind) {
802 case OMPC_DEFAULTMAP_scalar:
803 case OMPC_DEFAULTMAP_pointer:
804 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_default);
807 case OMPC_DEFAULTMAP_aggregate:
808 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
809 default:
810 break;
811 }
812 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
813 }
814 bool mustBeFirstprivateAtLevel(unsigned Level,
815 OpenMPDefaultmapClauseKind Kind) const {
817 getDefaultmapModifierAtLevel(Level, Kind);
818 return mustBeFirstprivateBase(M, Kind);
819 }
820 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
821 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
822 return mustBeFirstprivateBase(M, Kind);
823 }
824
825 /// Checks if the specified variable is a threadprivate.
826 bool isThreadPrivate(VarDecl *D) {
827 const DSAVarData DVar = getTopDSA(D, false);
828 return isOpenMPThreadPrivate(DVar.CKind);
829 }
830
831 /// Marks current region as ordered (it has an 'ordered' clause).
832 void setOrderedRegion(bool IsOrdered, const Expr *Param,
833 OMPOrderedClause *Clause) {
834 if (IsOrdered)
835 getTopOfStack().OrderedRegion.emplace(Param, Clause);
836 else
837 getTopOfStack().OrderedRegion.reset();
838 }
839 /// Returns true, if region is ordered (has associated 'ordered' clause),
840 /// false - otherwise.
841 bool isOrderedRegion() const {
842 if (const SharingMapTy *Top = getTopOfStackOrNull())
843 return Top->OrderedRegion.has_value();
844 return false;
845 }
846 /// Returns optional parameter for the ordered region.
847 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
848 if (const SharingMapTy *Top = getTopOfStackOrNull())
849 if (Top->OrderedRegion)
850 return Top->OrderedRegion.value();
851 return std::make_pair(nullptr, nullptr);
852 }
853 /// Returns true, if parent region is ordered (has associated
854 /// 'ordered' clause), false - otherwise.
855 bool isParentOrderedRegion() const {
856 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
857 return Parent->OrderedRegion.has_value();
858 return false;
859 }
860 /// Returns optional parameter for the ordered region.
861 std::pair<const Expr *, OMPOrderedClause *>
862 getParentOrderedRegionParam() const {
863 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
864 if (Parent->OrderedRegion)
865 return Parent->OrderedRegion.value();
866 return std::make_pair(nullptr, nullptr);
867 }
868 /// Marks current region as nowait (it has a 'nowait' clause).
869 void setNowaitRegion(bool IsNowait = true) {
870 getTopOfStack().NowaitRegion = IsNowait;
871 }
872 /// Returns true, if parent region is nowait (has associated
873 /// 'nowait' clause), false - otherwise.
874 bool isParentNowaitRegion() const {
875 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
876 return Parent->NowaitRegion;
877 return false;
878 }
879 /// Marks current region as untied (it has a 'untied' clause).
880 void setUntiedRegion(bool IsUntied = true) {
881 getTopOfStack().UntiedRegion = IsUntied;
882 }
883 /// Return true if current region is untied.
884 bool isUntiedRegion() const {
885 const SharingMapTy *Top = getTopOfStackOrNull();
886 return Top ? Top->UntiedRegion : false;
887 }
888 /// Marks parent region as cancel region.
889 void setParentCancelRegion(bool Cancel = true) {
890 if (SharingMapTy *Parent = getSecondOnStackOrNull())
891 Parent->CancelRegion |= Cancel;
892 }
893 /// Return true if current region has inner cancel construct.
894 bool isCancelRegion() const {
895 const SharingMapTy *Top = getTopOfStackOrNull();
896 return Top ? Top->CancelRegion : false;
897 }
898
899 /// Mark that parent region already has scan directive.
900 void setParentHasScanDirective(SourceLocation Loc) {
901 if (SharingMapTy *Parent = getSecondOnStackOrNull())
902 Parent->PrevScanLocation = Loc;
903 }
904 /// Return true if current region has inner cancel construct.
905 bool doesParentHasScanDirective() const {
906 const SharingMapTy *Top = getSecondOnStackOrNull();
907 return Top ? Top->PrevScanLocation.isValid() : false;
908 }
909 /// Return true if current region has inner cancel construct.
910 SourceLocation getParentScanDirectiveLoc() const {
911 const SharingMapTy *Top = getSecondOnStackOrNull();
912 return Top ? Top->PrevScanLocation : SourceLocation();
913 }
914 /// Mark that parent region already has ordered directive.
915 void setParentHasOrderedDirective(SourceLocation Loc) {
916 if (SharingMapTy *Parent = getSecondOnStackOrNull())
917 Parent->PrevOrderedLocation = Loc;
918 }
919 /// Return true if current region has inner ordered construct.
920 bool doesParentHasOrderedDirective() const {
921 const SharingMapTy *Top = getSecondOnStackOrNull();
922 return Top ? Top->PrevOrderedLocation.isValid() : false;
923 }
924 /// Returns the location of the previously specified ordered directive.
925 SourceLocation getParentOrderedDirectiveLoc() const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevOrderedLocation : SourceLocation();
928 }
929
930 /// Set collapse value for the region.
931 void setAssociatedLoops(unsigned Val) {
932 getTopOfStack().AssociatedLoops = Val;
933 if (Val > 1)
934 getTopOfStack().HasMutipleLoops = true;
935 }
936 /// Return collapse value for region.
937 unsigned getAssociatedLoops() const {
938 const SharingMapTy *Top = getTopOfStackOrNull();
939 return Top ? Top->AssociatedLoops : 0;
940 }
941 /// Returns true if the construct is associated with multiple loops.
942 bool hasMutipleLoops() const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->HasMutipleLoops : false;
945 }
946
947 /// Marks current target region as one with closely nested teams
948 /// region.
949 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
950 if (SharingMapTy *Parent = getSecondOnStackOrNull())
951 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
952 }
953 /// Returns true, if current region has closely nested teams region.
954 bool hasInnerTeamsRegion() const {
955 return getInnerTeamsRegionLoc().isValid();
956 }
957 /// Returns location of the nested teams region (if any).
958 SourceLocation getInnerTeamsRegionLoc() const {
959 const SharingMapTy *Top = getTopOfStackOrNull();
960 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
961 }
962
963 Scope *getCurScope() const {
964 const SharingMapTy *Top = getTopOfStackOrNull();
965 return Top ? Top->CurScope : nullptr;
966 }
967 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
968 SourceLocation getConstructLoc() const {
969 const SharingMapTy *Top = getTopOfStackOrNull();
970 return Top ? Top->ConstructLoc : SourceLocation();
971 }
972
973 /// Do the check specified in \a Check to all component lists and return true
974 /// if any issue is found.
975 bool checkMappableExprComponentListsForDecl(
976 const ValueDecl *VD, bool CurrentRegionOnly,
977 const llvm::function_ref<
980 Check) const {
981 if (isStackEmpty())
982 return false;
983 auto SI = begin();
984 auto SE = end();
985
986 if (SI == SE)
987 return false;
988
989 if (CurrentRegionOnly)
990 SE = std::next(SI);
991 else
992 std::advance(SI, 1);
993
994 for (; SI != SE; ++SI) {
995 auto MI = SI->MappedExprComponents.find(VD);
996 if (MI != SI->MappedExprComponents.end())
998 MI->second.Components)
999 if (Check(L, MI->second.Kind))
1000 return true;
1001 }
1002 return false;
1003 }
1004
1005 /// Do the check specified in \a Check to all component lists at a given level
1006 /// and return true if any issue is found.
1007 bool checkMappableExprComponentListsForDeclAtLevel(
1008 const ValueDecl *VD, unsigned Level,
1009 const llvm::function_ref<
1012 Check) const {
1013 if (getStackSize() <= Level)
1014 return false;
1015
1016 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1017 auto MI = StackElem.MappedExprComponents.find(VD);
1018 if (MI != StackElem.MappedExprComponents.end())
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1022 return true;
1023 return false;
1024 }
1025
1026 /// Create a new mappable expression component list associated with a given
1027 /// declaration and initialize it with the provided list of components.
1028 void addMappableExpressionComponents(
1029 const ValueDecl *VD,
1031 OpenMPClauseKind WhereFoundClauseKind) {
1032 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1033 // Create new entry and append the new components there.
1034 MEC.Components.resize(MEC.Components.size() + 1);
1035 MEC.Components.back().append(Components.begin(), Components.end());
1036 MEC.Kind = WhereFoundClauseKind;
1037 }
1038
1039 unsigned getNestingLevel() const {
1040 assert(!isStackEmpty());
1041 return getStackSize() - 1;
1042 }
1043 void addDoacrossDependClause(OMPDependClause *C,
1044 const OperatorOffsetTy &OpsOffs) {
1045 SharingMapTy *Parent = getSecondOnStackOrNull();
1046 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1047 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1048 }
1049 llvm::iterator_range<DoacrossDependMapTy::const_iterator>
1050 getDoacrossDependClauses() const {
1051 const SharingMapTy &StackElem = getTopOfStack();
1052 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1053 const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
1054 return llvm::make_range(Ref.begin(), Ref.end());
1055 }
1056 return llvm::make_range(StackElem.DoacrossDepends.end(),
1057 StackElem.DoacrossDepends.end());
1058 }
1059
1060 // Store types of classes which have been explicitly mapped
1061 void addMappedClassesQualTypes(QualType QT) {
1062 SharingMapTy &StackElem = getTopOfStack();
1063 StackElem.MappedClassesQualTypes.insert(QT);
1064 }
1065
1066 // Return set of mapped classes types
1067 bool isClassPreviouslyMapped(QualType QT) const {
1068 const SharingMapTy &StackElem = getTopOfStack();
1069 return StackElem.MappedClassesQualTypes.contains(QT);
1070 }
1071
1072 /// Adds global declare target to the parent target region.
1073 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1074 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1075 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1076 "Expected declare target link global.");
1077 for (auto &Elem : *this) {
1078 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1079 Elem.DeclareTargetLinkVarDecls.push_back(E);
1080 return;
1081 }
1082 }
1083 }
1084
1085 /// Returns the list of globals with declare target link if current directive
1086 /// is target.
1087 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1088 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1089 "Expected target executable directive.");
1090 return getTopOfStack().DeclareTargetLinkVarDecls;
1091 }
1092
1093 /// Adds list of allocators expressions.
1094 void addInnerAllocatorExpr(Expr *E) {
1095 getTopOfStack().InnerUsedAllocators.push_back(E);
1096 }
1097 /// Return list of used allocators.
1098 ArrayRef<Expr *> getInnerAllocators() const {
1099 return getTopOfStack().InnerUsedAllocators;
1100 }
1101 /// Marks the declaration as implicitly firstprivate nin the task-based
1102 /// regions.
1103 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1104 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1105 }
1106 /// Checks if the decl is implicitly firstprivate in the task-based region.
1107 bool isImplicitTaskFirstprivate(Decl *D) const {
1108 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1109 }
1110
1111 /// Marks decl as used in uses_allocators clause as the allocator.
1112 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1113 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1114 }
1115 /// Checks if specified decl is used in uses allocator clause as the
1116 /// allocator.
1117 Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(unsigned Level,
1118 const Decl *D) const {
1119 const SharingMapTy &StackElem = getTopOfStack();
1120 auto I = StackElem.UsesAllocatorsDecls.find(D);
1121 if (I == StackElem.UsesAllocatorsDecls.end())
1122 return None;
1123 return I->getSecond();
1124 }
1125 Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(const Decl *D) const {
1126 const SharingMapTy &StackElem = getTopOfStack();
1127 auto I = StackElem.UsesAllocatorsDecls.find(D);
1128 if (I == StackElem.UsesAllocatorsDecls.end())
1129 return None;
1130 return I->getSecond();
1131 }
1132
1133 void addDeclareMapperVarRef(Expr *Ref) {
1134 SharingMapTy &StackElem = getTopOfStack();
1135 StackElem.DeclareMapperVar = Ref;
1136 }
1137 const Expr *getDeclareMapperVarRef() const {
1138 const SharingMapTy *Top = getTopOfStackOrNull();
1139 return Top ? Top->DeclareMapperVar : nullptr;
1140 }
1141 /// get captured field from ImplicitDefaultFirstprivateFDs
1142 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1143 const_iterator I = begin();
1144 const_iterator EndI = end();
1145 size_t StackLevel = getStackSize();
1146 for (; I != EndI; ++I) {
1147 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1148 break;
1149 StackLevel--;
1150 }
1151 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1152 if (I == EndI)
1153 return nullptr;
1154 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1155 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1156 return IFD.VD;
1157 return nullptr;
1158 }
1159 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1160 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1161 const_iterator I = begin();
1162 const_iterator EndI = end();
1163 for (; I != EndI; ++I)
1164 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1165 break;
1166 if (I == EndI)
1167 return false;
1168 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1169 if (IFD.VD == VD)
1170 return true;
1171 return false;
1172 }
1173 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1174 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1175 iterator I = begin();
1176 const_iterator EndI = end();
1177 size_t StackLevel = getStackSize();
1178 for (; I != EndI; ++I) {
1179 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1180 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1181 break;
1182 }
1183 StackLevel--;
1184 }
1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1186 }
1187};
1188
1189bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1190 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1191}
1192
1193bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1194 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1195 DKind == OMPD_unknown;
1196}
1197
1198} // namespace
1199
1200static const Expr *getExprAsWritten(const Expr *E) {
1201 if (const auto *FE = dyn_cast<FullExpr>(E))
1202 E = FE->getSubExpr();
1203
1204 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1205 E = MTE->getSubExpr();
1206
1207 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1208 E = Binder->getSubExpr();
1209
1210 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1211 E = ICE->getSubExprAsWritten();
1212 return E->IgnoreParens();
1213}
1214
1216 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1217}
1218
1219static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1220 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1221 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1222 D = ME->getMemberDecl();
1223 const auto *VD = dyn_cast<VarDecl>(D);
1224 const auto *FD = dyn_cast<FieldDecl>(D);
1225 if (VD != nullptr) {
1226 VD = VD->getCanonicalDecl();
1227 D = VD;
1228 } else {
1229 assert(FD);
1230 FD = FD->getCanonicalDecl();
1231 D = FD;
1232 }
1233 return D;
1234}
1235
1237 return const_cast<ValueDecl *>(
1238 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1239}
1240
1241DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1242 ValueDecl *D) const {
1243 D = getCanonicalDecl(D);
1244 auto *VD = dyn_cast<VarDecl>(D);
1245 const auto *FD = dyn_cast<FieldDecl>(D);
1246 DSAVarData DVar;
1247 if (Iter == end()) {
1248 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1249 // in a region but not in construct]
1250 // File-scope or namespace-scope variables referenced in called routines
1251 // in the region are shared unless they appear in a threadprivate
1252 // directive.
1253 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1254 DVar.CKind = OMPC_shared;
1255
1256 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1257 // in a region but not in construct]
1258 // Variables with static storage duration that are declared in called
1259 // routines in the region are shared.
1260 if (VD && VD->hasGlobalStorage())
1261 DVar.CKind = OMPC_shared;
1262
1263 // Non-static data members are shared by default.
1264 if (FD)
1265 DVar.CKind = OMPC_shared;
1266
1267 return DVar;
1268 }
1269
1270 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1271 // in a Construct, C/C++, predetermined, p.1]
1272 // Variables with automatic storage duration that are declared in a scope
1273 // inside the construct are private.
1274 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1275 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1276 DVar.CKind = OMPC_private;
1277 return DVar;
1278 }
1279
1280 DVar.DKind = Iter->Directive;
1281 // Explicitly specified attributes and local variables with predetermined
1282 // attributes.
1283 if (Iter->SharingMap.count(D)) {
1284 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1285 DVar.RefExpr = Data.RefExpr.getPointer();
1286 DVar.PrivateCopy = Data.PrivateCopy;
1287 DVar.CKind = Data.Attributes;
1288 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1289 DVar.Modifier = Data.Modifier;
1290 DVar.AppliedToPointee = Data.AppliedToPointee;
1291 return DVar;
1292 }
1293
1294 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1295 // in a Construct, C/C++, implicitly determined, p.1]
1296 // In a parallel or task construct, the data-sharing attributes of these
1297 // variables are determined by the default clause, if present.
1298 switch (Iter->DefaultAttr) {
1299 case DSA_shared:
1300 DVar.CKind = OMPC_shared;
1301 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1302 return DVar;
1303 case DSA_none:
1304 return DVar;
1305 case DSA_firstprivate:
1306 if (VD && VD->getStorageDuration() == SD_Static &&
1307 VD->getDeclContext()->isFileContext()) {
1308 DVar.CKind = OMPC_unknown;
1309 } else {
1310 DVar.CKind = OMPC_firstprivate;
1311 }
1312 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1313 return DVar;
1314 case DSA_private:
1315 // each variable with static storage duration that is declared
1316 // in a namespace or global scope and referenced in the construct,
1317 // and that does not have a predetermined data-sharing attribute
1318 if (VD && VD->getStorageDuration() == SD_Static &&
1319 VD->getDeclContext()->isFileContext()) {
1320 DVar.CKind = OMPC_unknown;
1321 } else {
1322 DVar.CKind = OMPC_private;
1323 }
1324 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1325 return DVar;
1326 case DSA_unspecified:
1327 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1328 // in a Construct, implicitly determined, p.2]
1329 // In a parallel construct, if no default clause is present, these
1330 // variables are shared.
1331 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1332 if ((isOpenMPParallelDirective(DVar.DKind) &&
1333 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1334 isOpenMPTeamsDirective(DVar.DKind)) {
1335 DVar.CKind = OMPC_shared;
1336 return DVar;
1337 }
1338
1339 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1340 // in a Construct, implicitly determined, p.4]
1341 // In a task construct, if no default clause is present, a variable that in
1342 // the enclosing context is determined to be shared by all implicit tasks
1343 // bound to the current team is shared.
1344 if (isOpenMPTaskingDirective(DVar.DKind)) {
1345 DSAVarData DVarTemp;
1346 const_iterator I = Iter, E = end();
1347 do {
1348 ++I;
1349 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1350 // Referenced in a Construct, implicitly determined, p.6]
1351 // In a task construct, if no default clause is present, a variable
1352 // whose data-sharing attribute is not determined by the rules above is
1353 // firstprivate.
1354 DVarTemp = getDSA(I, D);
1355 if (DVarTemp.CKind != OMPC_shared) {
1356 DVar.RefExpr = nullptr;
1357 DVar.CKind = OMPC_firstprivate;
1358 return DVar;
1359 }
1360 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1361 DVar.CKind =
1362 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1363 return DVar;
1364 }
1365 }
1366 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1367 // in a Construct, implicitly determined, p.3]
1368 // For constructs other than task, if no default clause is present, these
1369 // variables inherit their data-sharing attributes from the enclosing
1370 // context.
1371 return getDSA(++Iter, D);
1372}
1373
1374const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1375 const Expr *NewDE) {
1376 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1377 D = getCanonicalDecl(D);
1378 SharingMapTy &StackElem = getTopOfStack();
1379 auto It = StackElem.AlignedMap.find(D);
1380 if (It == StackElem.AlignedMap.end()) {
1381 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1382 StackElem.AlignedMap[D] = NewDE;
1383 return nullptr;
1384 }
1385 assert(It->second && "Unexpected nullptr expr in the aligned map");
1386 return It->second;
1387}
1388
1389const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1390 const Expr *NewDE) {
1391 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1392 D = getCanonicalDecl(D);
1393 SharingMapTy &StackElem = getTopOfStack();
1394 auto It = StackElem.NontemporalMap.find(D);
1395 if (It == StackElem.NontemporalMap.end()) {
1396 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1397 StackElem.NontemporalMap[D] = NewDE;
1398 return nullptr;
1399 }
1400 assert(It->second && "Unexpected nullptr expr in the aligned map");
1401 return It->second;
1402}
1403
1404void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1405 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1406 D = getCanonicalDecl(D);
1407 SharingMapTy &StackElem = getTopOfStack();
1408 StackElem.LCVMap.try_emplace(
1409 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1410}
1411
1412const DSAStackTy::LCDeclInfo
1413DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1414 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1415 D = getCanonicalDecl(D);
1416 const SharingMapTy &StackElem = getTopOfStack();
1417 auto It = StackElem.LCVMap.find(D);
1418 if (It != StackElem.LCVMap.end())
1419 return It->second;
1420 return {0, nullptr};
1421}
1422
1423const DSAStackTy::LCDeclInfo
1424DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1425 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1426 D = getCanonicalDecl(D);
1427 for (unsigned I = Level + 1; I > 0; --I) {
1428 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1429 auto It = StackElem.LCVMap.find(D);
1430 if (It != StackElem.LCVMap.end())
1431 return It->second;
1432 }
1433 return {0, nullptr};
1434}
1435
1436const DSAStackTy::LCDeclInfo
1437DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1438 const SharingMapTy *Parent = getSecondOnStackOrNull();
1439 assert(Parent && "Data-sharing attributes stack is empty");
1440 D = getCanonicalDecl(D);
1441 auto It = Parent->LCVMap.find(D);
1442 if (It != Parent->LCVMap.end())
1443 return It->second;
1444 return {0, nullptr};
1445}
1446
1447const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1448 const SharingMapTy *Parent = getSecondOnStackOrNull();
1449 assert(Parent && "Data-sharing attributes stack is empty");
1450 if (Parent->LCVMap.size() < I)
1451 return nullptr;
1452 for (const auto &Pair : Parent->LCVMap)
1453 if (Pair.second.first == I)
1454 return Pair.first;
1455 return nullptr;
1456}
1457
1458void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1459 DeclRefExpr *PrivateCopy, unsigned Modifier,
1460 bool AppliedToPointee) {
1461 D = getCanonicalDecl(D);
1462 if (A == OMPC_threadprivate) {
1463 DSAInfo &Data = Threadprivates[D];
1464 Data.Attributes = A;
1465 Data.RefExpr.setPointer(E);
1466 Data.PrivateCopy = nullptr;
1467 Data.Modifier = Modifier;
1468 } else {
1469 DSAInfo &Data = getTopOfStack().SharingMap[D];
1470 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1471 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1472 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1473 (isLoopControlVariable(D).first && A == OMPC_private));
1474 Data.Modifier = Modifier;
1475 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1476 Data.RefExpr.setInt(/*IntVal=*/true);
1477 return;
1478 }
1479 const bool IsLastprivate =
1480 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1481 Data.Attributes = A;
1482 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1483 Data.PrivateCopy = PrivateCopy;
1484 Data.AppliedToPointee = AppliedToPointee;
1485 if (PrivateCopy) {
1486 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1487 Data.Modifier = Modifier;
1488 Data.Attributes = A;
1489 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1490 Data.PrivateCopy = nullptr;
1491 Data.AppliedToPointee = AppliedToPointee;
1492 }
1493 }
1494}
1495
1496/// Build a variable declaration for OpenMP loop iteration variable.
1498 StringRef Name, const AttrVec *Attrs = nullptr,
1499 DeclRefExpr *OrigRef = nullptr) {
1500 DeclContext *DC = SemaRef.CurContext;
1501 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1502 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1503 auto *Decl =
1504 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1505 if (Attrs) {
1506 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1507 I != E; ++I)
1508 Decl->addAttr(*I);
1509 }
1510 Decl->setImplicit();
1511 if (OrigRef) {
1512 Decl->addAttr(
1513 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1514 }
1515 return Decl;
1516}
1517
1519 SourceLocation Loc,
1520 bool RefersToCapture = false) {
1521 D->setReferenced();
1522 D->markUsed(S.Context);
1524 SourceLocation(), D, RefersToCapture, Loc, Ty,
1525 VK_LValue);
1526}
1527
1528void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1529 BinaryOperatorKind BOK) {
1530 D = getCanonicalDecl(D);
1531 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1532 assert(
1533 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1534 "Additional reduction info may be specified only for reduction items.");
1535 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1536 assert(ReductionData.ReductionRange.isInvalid() &&
1537 (getTopOfStack().Directive == OMPD_taskgroup ||
1538 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1539 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1540 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1541 "Additional reduction info may be specified only once for reduction "
1542 "items.");
1543 ReductionData.set(BOK, SR);
1544 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1545 if (!TaskgroupReductionRef) {
1546 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1547 SemaRef.Context.VoidPtrTy, ".task_red.");
1548 TaskgroupReductionRef =
1549 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1550 }
1551}
1552
1553void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1554 const Expr *ReductionRef) {
1555 D = getCanonicalDecl(D);
1556 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1557 assert(
1558 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1559 "Additional reduction info may be specified only for reduction items.");
1560 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1561 assert(ReductionData.ReductionRange.isInvalid() &&
1562 (getTopOfStack().Directive == OMPD_taskgroup ||
1563 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1564 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1565 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1566 "Additional reduction info may be specified only once for reduction "
1567 "items.");
1568 ReductionData.set(ReductionRef, SR);
1569 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1570 if (!TaskgroupReductionRef) {
1571 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1572 SemaRef.Context.VoidPtrTy, ".task_red.");
1573 TaskgroupReductionRef =
1574 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1575 }
1576}
1577
1578const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1579 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1580 Expr *&TaskgroupDescriptor) const {
1581 D = getCanonicalDecl(D);
1582 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1583 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1584 const DSAInfo &Data = I->SharingMap.lookup(D);
1585 if (Data.Attributes != OMPC_reduction ||
1586 Data.Modifier != OMPC_REDUCTION_task)
1587 continue;
1588 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1589 if (!ReductionData.ReductionOp ||
1590 ReductionData.ReductionOp.is<const Expr *>())
1591 return DSAVarData();
1592 SR = ReductionData.ReductionRange;
1593 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1594 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1595 "expression for the descriptor is not "
1596 "set.");
1597 TaskgroupDescriptor = I->TaskgroupReductionRef;
1598 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1599 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1600 /*AppliedToPointee=*/false);
1601 }
1602 return DSAVarData();
1603}
1604
1605const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1606 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1607 Expr *&TaskgroupDescriptor) const {
1608 D = getCanonicalDecl(D);
1609 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1610 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1611 const DSAInfo &Data = I->SharingMap.lookup(D);
1612 if (Data.Attributes != OMPC_reduction ||
1613 Data.Modifier != OMPC_REDUCTION_task)
1614 continue;
1615 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1616 if (!ReductionData.ReductionOp ||
1617 !ReductionData.ReductionOp.is<const Expr *>())
1618 return DSAVarData();
1619 SR = ReductionData.ReductionRange;
1620 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1621 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1622 "expression for the descriptor is not "
1623 "set.");
1624 TaskgroupDescriptor = I->TaskgroupReductionRef;
1625 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1626 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1627 /*AppliedToPointee=*/false);
1628 }
1629 return DSAVarData();
1630}
1631
1632bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1633 D = D->getCanonicalDecl();
1634 for (const_iterator E = end(); I != E; ++I) {
1635 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1636 isOpenMPTargetExecutionDirective(I->Directive)) {
1637 if (I->CurScope) {
1638 Scope *TopScope = I->CurScope->getParent();
1639 Scope *CurScope = getCurScope();
1640 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1641 CurScope = CurScope->getParent();
1642 return CurScope != TopScope;
1643 }
1644 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1645 if (I->Context == DC)
1646 return true;
1647 return false;
1648 }
1649 }
1650 return false;
1651}
1652
1654 bool AcceptIfMutable = true,
1655 bool *IsClassType = nullptr) {
1656 ASTContext &Context = SemaRef.getASTContext();
1657 Type = Type.getNonReferenceType().getCanonicalType();
1658 bool IsConstant = Type.isConstant(Context);
1659 Type = Context.getBaseElementType(Type);
1660 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1662 : nullptr;
1663 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1664 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1665 RD = CTD->getTemplatedDecl();
1666 if (IsClassType)
1667 *IsClassType = RD;
1668 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1669 RD->hasDefinition() && RD->hasMutableFields());
1670}
1671
1672static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1674 SourceLocation ELoc,
1675 bool AcceptIfMutable = true,
1676 bool ListItemNotVar = false) {
1677 ASTContext &Context = SemaRef.getASTContext();
1678 bool IsClassType;
1679 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1680 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1681 : IsClassType ? diag::err_omp_const_not_mutable_variable
1682 : diag::err_omp_const_variable;
1683 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1684 if (!ListItemNotVar && D) {
1685 const VarDecl *VD = dyn_cast<VarDecl>(D);
1686 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1688 SemaRef.Diag(D->getLocation(),
1689 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1690 << D;
1691 }
1692 return true;
1693 }
1694 return false;
1695}
1696
1697const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1698 bool FromParent) {
1699 D = getCanonicalDecl(D);
1700 DSAVarData DVar;
1701
1702 auto *VD = dyn_cast<VarDecl>(D);
1703 auto TI = Threadprivates.find(D);
1704 if (TI != Threadprivates.end()) {
1705 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1706 DVar.CKind = OMPC_threadprivate;
1707 DVar.Modifier = TI->getSecond().Modifier;
1708 return DVar;
1709 }
1710 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1711 DVar.RefExpr = buildDeclRefExpr(
1712 SemaRef, VD, D->getType().getNonReferenceType(),
1713 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1714 DVar.CKind = OMPC_threadprivate;
1715 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1716 return DVar;
1717 }
1718 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1719 // in a Construct, C/C++, predetermined, p.1]
1720 // Variables appearing in threadprivate directives are threadprivate.
1721 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1722 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1723 SemaRef.getLangOpts().OpenMPUseTLS &&
1724 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1725 (VD && VD->getStorageClass() == SC_Register &&
1726 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1727 DVar.RefExpr = buildDeclRefExpr(
1728 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1729 DVar.CKind = OMPC_threadprivate;
1730 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1731 return DVar;
1732 }
1733 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1734 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1735 !isLoopControlVariable(D).first) {
1736 const_iterator IterTarget =
1737 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1738 return isOpenMPTargetExecutionDirective(Data.Directive);
1739 });
1740 if (IterTarget != end()) {
1741 const_iterator ParentIterTarget = IterTarget + 1;
1742 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1743 if (isOpenMPLocal(VD, Iter)) {
1744 DVar.RefExpr =
1745 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1746 D->getLocation());
1747 DVar.CKind = OMPC_threadprivate;
1748 return DVar;
1749 }
1750 }
1751 if (!isClauseParsingMode() || IterTarget != begin()) {
1752 auto DSAIter = IterTarget->SharingMap.find(D);
1753 if (DSAIter != IterTarget->SharingMap.end() &&
1754 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1755 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1756 DVar.CKind = OMPC_threadprivate;
1757 return DVar;
1758 }
1759 const_iterator End = end();
1760 if (!SemaRef.isOpenMPCapturedByRef(D,
1761 std::distance(ParentIterTarget, End),
1762 /*OpenMPCaptureLevel=*/0)) {
1763 DVar.RefExpr =
1764 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1765 IterTarget->ConstructLoc);
1766 DVar.CKind = OMPC_threadprivate;
1767 return DVar;
1768 }
1769 }
1770 }
1771 }
1772
1773 if (isStackEmpty())
1774 // Not in OpenMP execution region and top scope was already checked.
1775 return DVar;
1776
1777 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1778 // in a Construct, C/C++, predetermined, p.4]
1779 // Static data members are shared.
1780 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1781 // in a Construct, C/C++, predetermined, p.7]
1782 // Variables with static storage duration that are declared in a scope
1783 // inside the construct are shared.
1784 if (VD && VD->isStaticDataMember()) {
1785 // Check for explicitly specified attributes.
1786 const_iterator I = begin();
1787 const_iterator EndI = end();
1788 if (FromParent && I != EndI)
1789 ++I;
1790 if (I != EndI) {
1791 auto It = I->SharingMap.find(D);
1792 if (It != I->SharingMap.end()) {
1793 const DSAInfo &Data = It->getSecond();
1794 DVar.RefExpr = Data.RefExpr.getPointer();
1795 DVar.PrivateCopy = Data.PrivateCopy;
1796 DVar.CKind = Data.Attributes;
1797 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1798 DVar.DKind = I->Directive;
1799 DVar.Modifier = Data.Modifier;
1800 DVar.AppliedToPointee = Data.AppliedToPointee;
1801 return DVar;
1802 }
1803 }
1804
1805 DVar.CKind = OMPC_shared;
1806 return DVar;
1807 }
1808
1809 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1810 // The predetermined shared attribute for const-qualified types having no
1811 // mutable members was removed after OpenMP 3.1.
1812 if (SemaRef.LangOpts.OpenMP <= 31) {
1813 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1814 // in a Construct, C/C++, predetermined, p.6]
1815 // Variables with const qualified type having no mutable member are
1816 // shared.
1817 if (isConstNotMutableType(SemaRef, D->getType())) {
1818 // Variables with const-qualified type having no mutable member may be
1819 // listed in a firstprivate clause, even if they are static data members.
1820 DSAVarData DVarTemp = hasInnermostDSA(
1821 D,
1822 [](OpenMPClauseKind C, bool) {
1823 return C == OMPC_firstprivate || C == OMPC_shared;
1824 },
1825 MatchesAlways, FromParent);
1826 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1827 return DVarTemp;
1828
1829 DVar.CKind = OMPC_shared;
1830 return DVar;
1831 }
1832 }
1833
1834 // Explicitly specified attributes and local variables with predetermined
1835 // attributes.
1836 const_iterator I = begin();
1837 const_iterator EndI = end();
1838 if (FromParent && I != EndI)
1839 ++I;
1840 if (I == EndI)
1841 return DVar;
1842 auto It = I->SharingMap.find(D);
1843 if (It != I->SharingMap.end()) {
1844 const DSAInfo &Data = It->getSecond();
1845 DVar.RefExpr = Data.RefExpr.getPointer();
1846 DVar.PrivateCopy = Data.PrivateCopy;
1847 DVar.CKind = Data.Attributes;
1848 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1849 DVar.DKind = I->Directive;
1850 DVar.Modifier = Data.Modifier;
1851 DVar.AppliedToPointee = Data.AppliedToPointee;
1852 }
1853
1854 return DVar;
1855}
1856
1857const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1858 bool FromParent) const {
1859 if (isStackEmpty()) {
1860 const_iterator I;
1861 return getDSA(I, D);
1862 }
1863 D = getCanonicalDecl(D);
1864 const_iterator StartI = begin();
1865 const_iterator EndI = end();
1866 if (FromParent && StartI != EndI)
1867 ++StartI;
1868 return getDSA(StartI, D);
1869}
1870
1871const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1872 unsigned Level) const {
1873 if (getStackSize() <= Level)
1874 return DSAVarData();
1875 D = getCanonicalDecl(D);
1876 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1877 return getDSA(StartI, D);
1878}
1879
1880const DSAStackTy::DSAVarData
1881DSAStackTy::hasDSA(ValueDecl *D,
1882 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1883 DefaultDataSharingAttributes)>
1884 CPred,
1885 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1886 bool FromParent) const {
1887 if (isStackEmpty())
1888 return {};
1889 D = getCanonicalDecl(D);
1890 const_iterator I = begin();
1891 const_iterator EndI = end();
1892 if (FromParent && I != EndI)
1893 ++I;
1894 for (; I != EndI; ++I) {
1895 if (!DPred(I->Directive) &&
1896 !isImplicitOrExplicitTaskingRegion(I->Directive))
1897 continue;
1898 const_iterator NewI = I;
1899 DSAVarData DVar = getDSA(NewI, D);
1900 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1901 return DVar;
1902 }
1903 return {};
1904}
1905
1906const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1907 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1908 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1909 bool FromParent) const {
1910 if (isStackEmpty())
1911 return {};
1912 D = getCanonicalDecl(D);
1913 const_iterator StartI = begin();
1914 const_iterator EndI = end();
1915 if (FromParent && StartI != EndI)
1916 ++StartI;
1917 if (StartI == EndI || !DPred(StartI->Directive))
1918 return {};
1919 const_iterator NewI = StartI;
1920 DSAVarData DVar = getDSA(NewI, D);
1921 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1922 ? DVar
1923 : DSAVarData();
1924}
1925
1926bool DSAStackTy::hasExplicitDSA(
1927 const ValueDecl *D,
1928 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1929 unsigned Level, bool NotLastprivate) const {
1930 if (getStackSize() <= Level)
1931 return false;
1932 D = getCanonicalDecl(D);
1933 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1934 auto I = StackElem.SharingMap.find(D);
1935 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1936 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1937 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1938 return true;
1939 // Check predetermined rules for the loop control variables.
1940 auto LI = StackElem.LCVMap.find(D);
1941 if (LI != StackElem.LCVMap.end())
1942 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1943 return false;
1944}
1945
1946bool DSAStackTy::hasExplicitDirective(
1947 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1948 unsigned Level) const {
1949 if (getStackSize() <= Level)
1950 return false;
1951 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1952 return DPred(StackElem.Directive);
1953}
1954
1955bool DSAStackTy::hasDirective(
1956 const llvm::function_ref<bool(OpenMPDirectiveKind,
1958 DPred,
1959 bool FromParent) const {
1960 // We look only in the enclosing region.
1961 size_t Skip = FromParent ? 2 : 1;
1962 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1963 I != E; ++I) {
1964 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1965 return true;
1966 }
1967 return false;
1968}
1969
1970void Sema::InitDataSharingAttributesStack() {
1971 VarDataSharingAttributesStack = new DSAStackTy(*this);
1972}
1973
1974#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
1975
1976void Sema::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
1977
1978void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
1979 DSAStack->popFunction(OldFSI);
1980}
1981
1983 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice &&
1984 "Expected OpenMP device compilation.");
1986}
1987
1988namespace {
1989/// Status of the function emission on the host/device.
1990enum class FunctionEmissionStatus {
1991 Emitted,
1992 Discarded,
1993 Unknown,
1994};
1995} // anonymous namespace
1996
1998 unsigned DiagID,
1999 FunctionDecl *FD) {
2000 assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
2001 "Expected OpenMP device compilation.");
2002
2003 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2004 if (FD) {
2005 FunctionEmissionStatus FES = getEmissionStatus(FD);
2006 switch (FES) {
2007 case FunctionEmissionStatus::Emitted:
2008 Kind = SemaDiagnosticBuilder::K_Immediate;
2009 break;
2010 case FunctionEmissionStatus::Unknown:
2011 // TODO: We should always delay diagnostics here in case a target
2012 // region is in a function we do not emit. However, as the
2013 // current diagnostics are associated with the function containing
2014 // the target region and we do not emit that one, we would miss out
2015 // on diagnostics for the target region itself. We need to anchor
2016 // the diagnostics with the new generated function *or* ensure we
2017 // emit diagnostics associated with the surrounding function.
2018 Kind = isOpenMPDeviceDelayedContext(*this)
2019 ? SemaDiagnosticBuilder::K_Deferred
2020 : SemaDiagnosticBuilder::K_Immediate;
2021 break;
2022 case FunctionEmissionStatus::TemplateDiscarded:
2023 case FunctionEmissionStatus::OMPDiscarded:
2024 Kind = SemaDiagnosticBuilder::K_Nop;
2025 break;
2026 case FunctionEmissionStatus::CUDADiscarded:
2027 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2028 break;
2029 }
2030 }
2031
2032 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2033}
2034
2036 unsigned DiagID,
2037 FunctionDecl *FD) {
2038 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice &&
2039 "Expected OpenMP host compilation.");
2040
2041 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2042 if (FD) {
2043 FunctionEmissionStatus FES = getEmissionStatus(FD);
2044 switch (FES) {
2045 case FunctionEmissionStatus::Emitted:
2046 Kind = SemaDiagnosticBuilder::K_Immediate;
2047 break;
2048 case FunctionEmissionStatus::Unknown:
2049 Kind = SemaDiagnosticBuilder::K_Deferred;
2050 break;
2051 case FunctionEmissionStatus::TemplateDiscarded:
2052 case FunctionEmissionStatus::OMPDiscarded:
2053 case FunctionEmissionStatus::CUDADiscarded:
2054 Kind = SemaDiagnosticBuilder::K_Nop;
2055 break;
2056 }
2057 }
2058
2059 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2060}
2061
2064 if (LO.OpenMP <= 45) {
2066 return OMPC_DEFAULTMAP_scalar;
2067 return OMPC_DEFAULTMAP_aggregate;
2068 }
2070 return OMPC_DEFAULTMAP_pointer;
2072 return OMPC_DEFAULTMAP_scalar;
2073 return OMPC_DEFAULTMAP_aggregate;
2074}
2075
2076bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2077 unsigned OpenMPCaptureLevel) const {
2078 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2079
2080 ASTContext &Ctx = getASTContext();
2081 bool IsByRef = true;
2082
2083 // Find the directive that is associated with the provided scope.
2085 QualType Ty = D->getType();
2086
2087 bool IsVariableUsedInMapClause = false;
2088 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2089 // This table summarizes how a given variable should be passed to the device
2090 // given its type and the clauses where it appears. This table is based on
2091 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2092 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2093 //
2094 // =========================================================================
2095 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2096 // | |(tofrom:scalar)| | pvt | | | |
2097 // =========================================================================
2098 // | scl | | | | - | | bycopy|
2099 // | scl | | - | x | - | - | bycopy|
2100 // | scl | | x | - | - | - | null |
2101 // | scl | x | | | - | | byref |
2102 // | scl | x | - | x | - | - | bycopy|
2103 // | scl | x | x | - | - | - | null |
2104 // | scl | | - | - | - | x | byref |
2105 // | scl | x | - | - | - | x | byref |
2106 //
2107 // | agg | n.a. | | | - | | byref |
2108 // | agg | n.a. | - | x | - | - | byref |
2109 // | agg | n.a. | x | - | - | - | null |
2110 // | agg | n.a. | - | - | - | x | byref |
2111 // | agg | n.a. | - | - | - | x[] | byref |
2112 //
2113 // | ptr | n.a. | | | - | | bycopy|
2114 // | ptr | n.a. | - | x | - | - | bycopy|
2115 // | ptr | n.a. | x | - | - | - | null |
2116 // | ptr | n.a. | - | - | - | x | byref |
2117 // | ptr | n.a. | - | - | - | x[] | bycopy|
2118 // | ptr | n.a. | - | - | x | | bycopy|
2119 // | ptr | n.a. | - | - | x | x | bycopy|
2120 // | ptr | n.a. | - | - | x | x[] | bycopy|
2121 // =========================================================================
2122 // Legend:
2123 // scl - scalar
2124 // ptr - pointer
2125 // agg - aggregate
2126 // x - applies
2127 // - - invalid in this combination
2128 // [] - mapped with an array section
2129 // byref - should be mapped by reference
2130 // byval - should be mapped by value
2131 // null - initialize a local variable to null on the device
2132 //
2133 // Observations:
2134 // - All scalar declarations that show up in a map clause have to be passed
2135 // by reference, because they may have been mapped in the enclosing data
2136 // environment.
2137 // - If the scalar value does not fit the size of uintptr, it has to be
2138 // passed by reference, regardless the result in the table above.
2139 // - For pointers mapped by value that have either an implicit map or an
2140 // array section, the runtime library may pass the NULL value to the
2141 // device instead of the value passed to it by the compiler.
2142
2143 if (Ty->isReferenceType())
2144 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2145
2146 // Locate map clauses and see if the variable being captured is referred to
2147 // in any of those clauses. Here we only care about variables, not fields,
2148 // because fields are part of aggregates.
2149 bool IsVariableAssociatedWithSection = false;
2150
2151 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2152 D, Level,
2153 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2155 MapExprComponents,
2156 OpenMPClauseKind WhereFoundClauseKind) {
2157 // Only the map clause information influences how a variable is
2158 // captured. E.g. is_device_ptr does not require changing the default
2159 // behavior.
2160 if (WhereFoundClauseKind != OMPC_map)
2161 return false;
2162
2163 auto EI = MapExprComponents.rbegin();
2164 auto EE = MapExprComponents.rend();
2165
2166 assert(EI != EE && "Invalid map expression!");
2167
2168 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2169 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2170
2171 ++EI;
2172 if (EI == EE)
2173 return false;
2174
2175 if (isa<ArraySubscriptExpr>(EI->getAssociatedExpression()) ||
2176 isa<OMPArraySectionExpr>(EI->getAssociatedExpression()) ||
2177 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2178 isa<OMPArrayShapingExpr>(EI->getAssociatedExpression())) {
2179 IsVariableAssociatedWithSection = true;
2180 // There is nothing more we need to know about this variable.
2181 return true;
2182 }
2183
2184 // Keep looking for more map info.
2185 return false;
2186 });
2187
2188 if (IsVariableUsedInMapClause) {
2189 // If variable is identified in a map clause it is always captured by
2190 // reference except if it is a pointer that is dereferenced somehow.
2191 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2192 } else {
2193 // By default, all the data that has a scalar type is mapped by copy
2194 // (except for reduction variables).
2195 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2196 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2197 !Ty->isAnyPointerType()) ||
2198 !Ty->isScalarType() ||
2199 DSAStack->isDefaultmapCapturedByRef(
2200 Level, getVariableCategoryFromDecl(LangOpts, D)) ||
2201 DSAStack->hasExplicitDSA(
2202 D,
2203 [](OpenMPClauseKind K, bool AppliedToPointee) {
2204 return K == OMPC_reduction && !AppliedToPointee;
2205 },
2206 Level);
2207 }
2208 }
2209
2210 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2211 IsByRef =
2212 ((IsVariableUsedInMapClause &&
2213 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2214 OMPD_target) ||
2215 !(DSAStack->hasExplicitDSA(
2216 D,
2217 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2218 return K == OMPC_firstprivate ||
2219 (K == OMPC_reduction && AppliedToPointee);
2220 },
2221 Level, /*NotLastprivate=*/true) ||
2222 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2223 // If the variable is artificial and must be captured by value - try to
2224 // capture by value.
2225 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2226 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2227 // If the variable is implicitly firstprivate and scalar - capture by
2228 // copy
2229 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2230 DSAStack->getDefaultDSA() == DSA_private) &&
2231 !DSAStack->hasExplicitDSA(
2232 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2233 Level) &&
2234 !DSAStack->isLoopControlVariable(D, Level).first);
2235 }
2236
2237 // When passing data by copy, we need to make sure it fits the uintptr size
2238 // and alignment, because the runtime library only deals with uintptr types.
2239 // If it does not fit the uintptr size, we need to pass the data by reference
2240 // instead.
2241 if (!IsByRef &&
2242 (Ctx.getTypeSizeInChars(Ty) >
2244 Ctx.getDeclAlign(D) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2245 IsByRef = true;
2246 }
2247
2248 return IsByRef;
2249}
2250
2251unsigned Sema::getOpenMPNestingLevel() const {
2252 assert(getLangOpts().OpenMP);
2253 return DSAStack->getNestingLevel();
2254}
2255
2257 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2258 DSAStack->isUntiedRegion();
2259}
2260
2262 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2263 !DSAStack->isClauseParsingMode()) ||
2264 DSAStack->hasDirective(
2266 SourceLocation) -> bool {
2268 },
2269 false);
2270}
2271
2273 // Only rebuild for Field.
2274 if (!dyn_cast<FieldDecl>(D))
2275 return false;
2276 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2277 D,
2278 [](OpenMPClauseKind C, bool AppliedToPointee,
2279 DefaultDataSharingAttributes DefaultAttr) {
2280 return isOpenMPPrivate(C) && !AppliedToPointee &&
2281 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2282 },
2283 [](OpenMPDirectiveKind) { return true; },
2284 DSAStack->isClauseParsingMode());
2285 if (DVarPrivate.CKind != OMPC_unknown)
2286 return true;
2287 return false;
2288}
2289
2291 Expr *CaptureExpr, bool WithInit,
2292 DeclContext *CurContext,
2293 bool AsExpression);
2294
2296 unsigned StopAt) {
2297 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2298 D = getCanonicalDecl(D);
2299
2300 auto *VD = dyn_cast<VarDecl>(D);
2301 // Do not capture constexpr variables.
2302 if (VD && VD->isConstexpr())
2303 return nullptr;
2304
2305 // If we want to determine whether the variable should be captured from the
2306 // perspective of the current capturing scope, and we've already left all the
2307 // capturing scopes of the top directive on the stack, check from the
2308 // perspective of its parent directive (if any) instead.
2309 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2310 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2311
2312 // If we are attempting to capture a global variable in a directive with
2313 // 'target' we return true so that this global is also mapped to the device.
2314 //
2315 if (VD && !VD->hasLocalStorage() &&
2316 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2317 if (isInOpenMPTargetExecutionDirective()) {
2318 DSAStackTy::DSAVarData DVarTop =
2319 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2320 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2321 return VD;
2322 // If the declaration is enclosed in a 'declare target' directive,
2323 // then it should not be captured.
2324 //
2325 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2326 return nullptr;
2327 CapturedRegionScopeInfo *CSI = nullptr;
2328 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2329 llvm::reverse(FunctionScopes),
2330 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2331 if (!isa<CapturingScopeInfo>(FSI))
2332 return nullptr;
2333 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2334 if (RSI->CapRegionKind == CR_OpenMP) {
2335 CSI = RSI;
2336 break;
2337 }
2338 }
2339 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2342 DSAStack->getDirective(CSI->OpenMPLevel));
2343 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2344 return VD;
2345 }
2346 if (isInOpenMPDeclareTargetContext()) {
2347 // Try to mark variable as declare target if it is used in capturing
2348 // regions.
2349 if (LangOpts.OpenMP <= 45 &&
2350 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2351 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2352 return nullptr;
2353 }
2354 }
2355
2356 if (CheckScopeInfo) {
2357 bool OpenMPFound = false;
2358 for (unsigned I = StopAt + 1; I > 0; --I) {
2359 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2360 if (!isa<CapturingScopeInfo>(FSI))
2361 return nullptr;
2362 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2363 if (RSI->CapRegionKind == CR_OpenMP) {
2364 OpenMPFound = true;
2365 break;
2366 }
2367 }
2368 if (!OpenMPFound)
2369 return nullptr;
2370 }
2371
2372 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2373 (!DSAStack->isClauseParsingMode() ||
2374 DSAStack->getParentDirective() != OMPD_unknown)) {
2375 auto &&Info = DSAStack->isLoopControlVariable(D);
2376 if (Info.first ||
2377 (VD && VD->hasLocalStorage() &&
2378 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2379 (VD && DSAStack->isForceVarCapturing()))
2380 return VD ? VD : Info.second;
2381 DSAStackTy::DSAVarData DVarTop =
2382 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2383 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2384 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2385 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2386 // Threadprivate variables must not be captured.
2387 if (isOpenMPThreadPrivate(DVarTop.CKind))
2388 return nullptr;
2389 // The variable is not private or it is the variable in the directive with
2390 // default(none) clause and not used in any clause.
2391 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2392 D,
2393 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2394 return isOpenMPPrivate(C) && !AppliedToPointee;
2395 },
2396 [](OpenMPDirectiveKind) { return true; },
2397 DSAStack->isClauseParsingMode());
2398 // Global shared must not be captured.
2399 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2400 ((DSAStack->getDefaultDSA() != DSA_none &&
2401 DSAStack->getDefaultDSA() != DSA_private &&
2402 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2403 DVarTop.CKind == OMPC_shared))
2404 return nullptr;
2405 auto *FD = dyn_cast<FieldDecl>(D);
2406 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2407 !DVarPrivate.PrivateCopy) {
2408 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2409 D,
2410 [](OpenMPClauseKind C, bool AppliedToPointee,
2411 DefaultDataSharingAttributes DefaultAttr) {
2412 return isOpenMPPrivate(C) && !AppliedToPointee &&
2413 (DefaultAttr == DSA_firstprivate ||
2414 DefaultAttr == DSA_private);
2415 },
2416 [](OpenMPDirectiveKind) { return true; },
2417 DSAStack->isClauseParsingMode());
2418 if (DVarPrivate.CKind == OMPC_unknown)
2419 return nullptr;
2420
2421 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2422 if (VD)
2423 return VD;
2424 if (getCurrentThisType().isNull())
2425 return nullptr;
2426 Expr *ThisExpr = BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2427 /*IsImplicit=*/true);
2428 const CXXScopeSpec CS = CXXScopeSpec();
2429 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2432 /*HadMultipleCandidates=*/false,
2436 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2437 CurContext->getParent(), /*AsExpression=*/false);
2438 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2439 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2440 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2441 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2442 return VD;
2443 }
2444 if (DVarPrivate.CKind != OMPC_unknown ||
2445 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2446 DSAStack->getDefaultDSA() == DSA_private ||
2447 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2448 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2449 }
2450 return nullptr;
2451}
2452
2453void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2454 unsigned Level) const {
2455 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2456}
2457
2459 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2460 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2461 DSAStack->loopInit();
2462}
2463
2465 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2466 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2467 DSAStack->resetPossibleLoopCounter();
2468 DSAStack->loopStart();
2469 }
2470}
2471
2473 unsigned CapLevel) const {
2474 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2475 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2476 (!DSAStack->isClauseParsingMode() ||
2477 DSAStack->getParentDirective() != OMPD_unknown)) {
2478 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2479 D,
2480 [](OpenMPClauseKind C, bool AppliedToPointee,
2481 DefaultDataSharingAttributes DefaultAttr) {
2482 return isOpenMPPrivate(C) && !AppliedToPointee &&
2483 DefaultAttr == DSA_private;
2484 },
2485 [](OpenMPDirectiveKind) { return true; },
2486 DSAStack->isClauseParsingMode());
2487 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2488 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2489 !DSAStack->isLoopControlVariable(D).first)
2490 return OMPC_private;
2491 }
2492 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2493 bool IsTriviallyCopyable =
2495 !D->getType()
2499 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2501 getOpenMPCaptureRegions(CaptureRegions, DKind);
2502 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2503 (IsTriviallyCopyable ||
2504 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2505 if (DSAStack->hasExplicitDSA(
2506 D,
2507 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2508 Level, /*NotLastprivate=*/true))
2509 return OMPC_firstprivate;
2510 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2511 if (DVar.CKind != OMPC_shared &&
2512 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2513 DSAStack->addImplicitTaskFirstprivate(Level, D);
2514 return OMPC_firstprivate;
2515 }
2516 }
2517 }
2518 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2519 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2520 DSAStack->resetPossibleLoopCounter(D);
2521 DSAStack->loopStart();
2522 return OMPC_private;
2523 }
2524 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2525 DSAStack->isLoopControlVariable(D).first) &&
2526 !DSAStack->hasExplicitDSA(
2527 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2528 Level) &&
2529 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2530 return OMPC_private;
2531 }
2532 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2533 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2534 DSAStack->isForceVarCapturing() &&
2535 !DSAStack->hasExplicitDSA(
2536 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2537 Level))
2538 return OMPC_private;
2539 }
2540 // User-defined allocators are private since they must be defined in the
2541 // context of target region.
2542 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2543 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2544 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2545 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2546 return OMPC_private;
2547 return (DSAStack->hasExplicitDSA(
2548 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2549 Level) ||
2550 (DSAStack->isClauseParsingMode() &&
2551 DSAStack->getClauseParsingMode() == OMPC_private) ||
2552 // Consider taskgroup reduction descriptor variable a private
2553 // to avoid possible capture in the region.
2554 (DSAStack->hasExplicitDirective(
2555 [](OpenMPDirectiveKind K) {
2556 return K == OMPD_taskgroup ||
2557 ((isOpenMPParallelDirective(K) ||
2558 isOpenMPWorksharingDirective(K)) &&
2559 !isOpenMPSimdDirective(K));
2560 },
2561 Level) &&
2562 DSAStack->isTaskgroupReductionRef(D, Level)))
2563 ? OMPC_private
2564 : OMPC_unknown;
2565}
2566
2568 unsigned Level) {
2569 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2570 D = getCanonicalDecl(D);
2571 OpenMPClauseKind OMPC = OMPC_unknown;
2572 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2573 const unsigned NewLevel = I - 1;
2574 if (DSAStack->hasExplicitDSA(
2575 D,
2576 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2577 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2578 OMPC = K;
2579 return true;
2580 }
2581 return false;
2582 },
2583 NewLevel))
2584 break;
2585 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2586 D, NewLevel,
2588 OpenMPClauseKind) { return true; })) {
2589 OMPC = OMPC_map;
2590 break;
2591 }
2592 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2593 NewLevel)) {
2594 OMPC = OMPC_map;
2595 if (DSAStack->mustBeFirstprivateAtLevel(
2596 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2597 OMPC = OMPC_firstprivate;
2598 break;
2599 }
2600 }
2601 if (OMPC != OMPC_unknown)
2602 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2603}
2604
2605bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2606 unsigned CaptureLevel) const {
2607 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2608 // Return true if the current level is no longer enclosed in a target region.
2609
2611 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2612 const auto *VD = dyn_cast<VarDecl>(D);
2613 return VD && !VD->hasLocalStorage() &&
2614 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2615 Level) &&
2616 Regions[CaptureLevel] != OMPD_task;
2617}
2618
2620 unsigned CaptureLevel) const {
2621 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2622 // Return true if the current level is no longer enclosed in a target region.
2623
2624 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2625 if (!VD->hasLocalStorage()) {
2626 if (isInOpenMPTargetExecutionDirective())
2627 return true;
2628 DSAStackTy::DSAVarData TopDVar =
2629 DSAStack->getTopDSA(D, /*FromParent=*/false);
2630 unsigned NumLevels =
2631 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2632 if (Level == 0)
2633 // non-file scope static variale with default(firstprivate)
2634 // should be gloabal captured.
2635 return (NumLevels == CaptureLevel + 1 &&
2636 (TopDVar.CKind != OMPC_shared ||
2637 DSAStack->getDefaultDSA() == DSA_firstprivate));
2638 do {
2639 --Level;
2640 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2641 if (DVar.CKind != OMPC_shared)
2642 return true;
2643 } while (Level > 0);
2644 }
2645 }
2646 return true;
2647}
2648
2649void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
2650
2652 OMPTraitInfo &TI) {
2653 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2654}
2655
2657 assert(isInOpenMPDeclareVariantScope() &&
2658 "Not in OpenMP declare variant scope!");
2659
2660 OMPDeclareVariantScopes.pop_back();
2661}
2662
2664 const FunctionDecl *Callee,
2665 SourceLocation Loc) {
2666 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
2668 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2669 // Ignore host functions during device analyzis.
2670 if (LangOpts.OpenMPIsDevice &&
2671 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2672 return;
2673 // Ignore nohost functions during host analyzis.
2674 if (!LangOpts.OpenMPIsDevice && DevTy &&
2675 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2676 return;
2677 const FunctionDecl *FD = Callee->getMostRecentDecl();
2678 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2679 if (LangOpts.OpenMPIsDevice && DevTy &&
2680 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2681 // Diagnose host function called during device codegen.
2682 StringRef HostDevTy =
2683 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2684 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2685 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2686 diag::note_omp_marked_device_type_here)
2687 << HostDevTy;
2688 return;
2689 }
2690 if (!LangOpts.OpenMPIsDevice && !LangOpts.OpenMPOffloadMandatory && DevTy &&
2691 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2692 // Diagnose nohost function called during host codegen.
2693 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2694 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2695 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2696 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2697 diag::note_omp_marked_device_type_here)
2698 << NoHostDevTy;
2699 }
2700}
2701
2703 const DeclarationNameInfo &DirName,
2704 Scope *CurScope, SourceLocation Loc) {
2705 DSAStack->push(DKind, DirName, CurScope, Loc);
2706 PushExpressionEvaluationContext(
2707 ExpressionEvaluationContext::PotentiallyEvaluated);
2708}
2709
2711 DSAStack->setClauseParsingMode(K);
2712}
2713
2715 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2716 CleanupVarDeclMarking();
2717}
2718
2719static std::pair<ValueDecl *, bool>
2720getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2721 SourceRange &ERange, bool AllowArraySection = false);
2722
2723/// Check consistency of the reduction clauses.
2724static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2725 ArrayRef<OMPClause *> Clauses) {
2726 bool InscanFound = false;
2727 SourceLocation InscanLoc;
2728 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2729 // A reduction clause without the inscan reduction-modifier may not appear on
2730 // a construct on which a reduction clause with the inscan reduction-modifier
2731 // appears.
2732 for (OMPClause *C : Clauses) {
2733 if (C->getClauseKind() != OMPC_reduction)
2734 continue;
2735 auto *RC = cast<OMPReductionClause>(C);
2736 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2737 InscanFound = true;
2738 InscanLoc = RC->getModifierLoc();
2739 continue;
2740 }
2741 if (RC->getModifier() == OMPC_REDUCTION_task) {
2742 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2743 // A reduction clause with the task reduction-modifier may only appear on
2744 // a parallel construct, a worksharing construct or a combined or
2745 // composite construct for which any of the aforementioned constructs is a
2746 // constituent construct and simd or loop are not constituent constructs.
2747 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2748 if (!(isOpenMPParallelDirective(CurDir) ||
2750 isOpenMPSimdDirective(CurDir))
2751 S.Diag(RC->getModifierLoc(),
2752 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2753 continue;
2754 }
2755 }
2756 if (InscanFound) {
2757 for (OMPClause *C : Clauses) {
2758 if (C->getClauseKind() != OMPC_reduction)
2759 continue;
2760 auto *RC = cast<OMPReductionClause>(C);
2761 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2762 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2763 ? RC->getBeginLoc()
2764 : RC->getModifierLoc(),
2765 diag::err_omp_inscan_reduction_expected);
2766 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2767 continue;
2768 }
2769 for (Expr *Ref : RC->varlists()) {
2770 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2771 SourceLocation ELoc;
2772 SourceRange ERange;
2773 Expr *SimpleRefExpr = Ref;
2774 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2775 /*AllowArraySection=*/true);
2776 ValueDecl *D = Res.first;
2777 if (!D)
2778 continue;
2779 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2780 S.Diag(Ref->getExprLoc(),
2781 diag::err_omp_reduction_not_inclusive_exclusive)
2782 << Ref->getSourceRange();
2783 }
2784 }
2785 }
2786 }
2787}
2788
2789static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2790 ArrayRef<OMPClause *> Clauses);
2791static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2792 bool WithInit);
2793
2794static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2795 const ValueDecl *D,
2796 const DSAStackTy::DSAVarData &DVar,
2797 bool IsLoopIterVar = false);
2798
2799void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2800 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2801 // A variable of class type (or array thereof) that appears in a lastprivate
2802 // clause requires an accessible, unambiguous default constructor for the
2803 // class type, unless the list item is also specified in a firstprivate
2804 // clause.
2805 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2806 for (OMPClause *C : D->clauses()) {
2807 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2808 SmallVector<Expr *, 8> PrivateCopies;
2809 for (Expr *DE : Clause->varlists()) {
2810 if (DE->isValueDependent() || DE->isTypeDependent()) {
2811 PrivateCopies.push_back(nullptr);
2812 continue;
2813 }
2814 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2815 auto *VD = cast<VarDecl>(DRE->getDecl());
2817 const DSAStackTy::DSAVarData DVar =
2818 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2819 if (DVar.CKind == OMPC_lastprivate) {
2820 // Generate helper private variable and initialize it with the
2821 // default value. The address of the original variable is replaced
2822 // by the address of the new private variable in CodeGen. This new
2823 // variable is not added to IdResolver, so the code in the OpenMP
2824 // region uses original variable for proper diagnostics.
2825 VarDecl *VDPrivate = buildVarDecl(
2826 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2827 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2828 ActOnUninitializedDecl(VDPrivate);
2829 if (VDPrivate->isInvalidDecl()) {
2830 PrivateCopies.push_back(nullptr);
2831 continue;
2832 }
2833 PrivateCopies.push_back(buildDeclRefExpr(
2834 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2835 } else {
2836 // The variable is also a firstprivate, so initialization sequence
2837 // for private copy is generated already.
2838 PrivateCopies.push_back(nullptr);
2839 }
2840 }
2841 Clause->setPrivateCopies(PrivateCopies);
2842 continue;
2843 }
2844 // Finalize nontemporal clause by handling private copies, if any.
2845 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2846 SmallVector<Expr *, 8> PrivateRefs;
2847 for (Expr *RefExpr : Clause->varlists()) {
2848 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2849 SourceLocation ELoc;
2850 SourceRange ERange;
2851 Expr *SimpleRefExpr = RefExpr;
2852 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2853 if (Res.second)
2854 // It will be analyzed later.
2855 PrivateRefs.push_back(RefExpr);
2856 ValueDecl *D = Res.first;
2857 if (!D)
2858 continue;
2859
2860 const DSAStackTy::DSAVarData DVar =
2861 DSAStack->getTopDSA(D, /*FromParent=*/false);
2862 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2863 : SimpleRefExpr);
2864 }
2865 Clause->setPrivateRefs(PrivateRefs);
2866 continue;
2867 }
2868 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2869 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2870 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2871 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2872 if (!DRE)
2873 continue;
2874 ValueDecl *VD = DRE->getDecl();
2875 if (!VD || !isa<VarDecl>(VD))
2876 continue;
2877 DSAStackTy::DSAVarData DVar =
2878 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2879 // OpenMP [2.12.5, target Construct]
2880 // Memory allocators that appear in a uses_allocators clause cannot
2881 // appear in other data-sharing attribute clauses or data-mapping
2882 // attribute clauses in the same construct.
2883 Expr *MapExpr = nullptr;
2884 if (DVar.RefExpr ||
2885 DSAStack->checkMappableExprComponentListsForDecl(
2886 VD, /*CurrentRegionOnly=*/true,
2887 [VD, &MapExpr](
2889 MapExprComponents,
2891 auto MI = MapExprComponents.rbegin();
2892 auto ME = MapExprComponents.rend();
2893 if (MI != ME &&
2894 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2895 VD->getCanonicalDecl()) {
2896 MapExpr = MI->getAssociatedExpression();
2897 return true;
2898 }
2899 return false;
2900 })) {
2901 Diag(D.Allocator->getExprLoc(),
2902 diag::err_omp_allocator_used_in_clauses)
2903 << D.Allocator->getSourceRange();
2904 if (DVar.RefExpr)
2905 reportOriginalDsa(*this, DSAStack, VD, DVar);
2906 else
2907 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2908 << MapExpr->getSourceRange();
2909 }
2910 }
2911 continue;
2912 }
2913 }
2914 // Check allocate clauses.
2915 if (!CurContext->isDependentContext())
2916 checkAllocateClauses(*this, DSAStack, D->clauses());
2917 checkReductionClauses(*this, DSAStack, D->clauses());
2918 }
2919
2920 DSAStack->pop();
2921 DiscardCleanupsInEvaluationContext();
2922 PopExpressionEvaluationContext();
2923}
2924
2926 Expr *NumIterations, Sema &SemaRef,
2927 Scope *S, DSAStackTy *Stack);
2928
2929namespace {
2930
2931class VarDeclFilterCCC final : public CorrectionCandidateCallback {
2932private:
2933 Sema &SemaRef;
2934
2935public:
2936 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
2937 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2938 NamedDecl *ND = Candidate.getCorrectionDecl();
2939 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
2940 return VD->hasGlobalStorage() &&
2941 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2942 SemaRef.getCurScope());
2943 }
2944 return false;
2945 }
2946
2947 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2948 return std::make_unique<VarDeclFilterCCC>(*this);
2949 }
2950};
2951
2952class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
2953private:
2954 Sema &SemaRef;
2955
2956public:
2957 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
2958 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2959 NamedDecl *ND = Candidate.getCorrectionDecl();
2960 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
2961 isa<FunctionDecl>(ND))) {
2962 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2963 SemaRef.getCurScope());
2964 }
2965 return false;
2966 }
2967
2968 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2969 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
2970 }
2971};
2972
2973} // namespace
2974
2976 CXXScopeSpec &ScopeSpec,
2977 const DeclarationNameInfo &Id,
2978 OpenMPDirectiveKind Kind) {
2979 LookupResult Lookup(*this, Id, LookupOrdinaryName);
2980 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
2981
2982 if (Lookup.isAmbiguous())
2983 return ExprError();
2984
2985 VarDecl *VD;
2986 if (!Lookup.isSingleResult()) {
2987 VarDeclFilterCCC CCC(*this);
2988 if (TypoCorrection Corrected =
2989 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
2990 CTK_ErrorRecovery)) {
2991 diagnoseTypo(Corrected,
2992 PDiag(Lookup.empty()
2993 ? diag::err_undeclared_var_use_suggest
2994 : diag::err_omp_expected_var_arg_suggest)
2995 << Id.getName());
2996 VD = Corrected.getCorrectionDeclAs<VarDecl>();
2997 } else {
2998 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
2999 : diag::err_omp_expected_var_arg)
3000 << Id.getName();
3001 return ExprError();
3002 }
3003 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3004 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3005 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3006 return ExprError();
3007 }
3008 Lookup.suppressDiagnostics();
3009
3010 // OpenMP [2.9.2, Syntax, C/C++]
3011 // Variables must be file-scope, namespace-scope, or static block-scope.
3012 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3013 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3014 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3015 bool IsDecl =
3017 Diag(VD->getLocation(),
3018 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3019 << VD;
3020 return ExprError();
3021 }
3022
3023 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3024 NamedDecl *ND = CanonicalVD;
3025 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3026 // A threadprivate directive for file-scope variables must appear outside
3027 // any definition or declaration.
3028 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3029 !getCurLexicalContext()->isTranslationUnit()) {
3030 Diag(Id.getLoc(), diag::err_omp_var_scope)
3031 << getOpenMPDirectiveName(Kind) << VD;
3032 bool IsDecl =
3034 Diag(VD->getLocation(),
3035 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3036 << VD;
3037 return ExprError();
3038 }
3039 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3040 // A threadprivate directive for static class member variables must appear
3041 // in the class definition, in the same scope in which the member
3042 // variables are declared.
3043 if (CanonicalVD->isStaticDataMember() &&
3044 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3045 Diag(Id.getLoc(), diag::err_omp_var_scope)
3046 << getOpenMPDirectiveName(Kind) << VD;
3047 bool IsDecl =
3049 Diag(VD->getLocation(),
3050 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3051 << VD;
3052 return ExprError();
3053 }
3054 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3055 // A threadprivate directive for namespace-scope variables must appear
3056 // outside any definition or declaration other than the namespace
3057 // definition itself.
3058 if (CanonicalVD->getDeclContext()->isNamespace() &&
3059 (!getCurLexicalContext()->isFileContext() ||
3060 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3061 Diag(Id.getLoc(), diag::err_omp_var_scope)
3062 << getOpenMPDirectiveName(Kind) << VD;
3063 bool IsDecl =
3065 Diag(VD->getLocation(),
3066 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3067 << VD;
3068 return ExprError();
3069 }
3070 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3071 // A threadprivate directive for static block-scope variables must appear
3072 // in the scope of the variable and not in a nested scope.
3073 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3074 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3075 Diag(Id.getLoc(), diag::err_omp_var_scope)
3076 << getOpenMPDirectiveName(Kind) << VD;
3077 bool IsDecl =
3079 Diag(VD->getLocation(),
3080 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3081 << VD;
3082 return ExprError();
3083 }
3084
3085 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3086 // A threadprivate directive must lexically precede all references to any
3087 // of the variables in its list.
3088 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3089 !DSAStack->isThreadPrivate(VD)) {
3090 Diag(Id.getLoc(), diag::err_omp_var_used)
3091 << getOpenMPDirectiveName(Kind) << VD;
3092 return ExprError();
3093 }
3094
3095 QualType ExprType = VD->getType().getNonReferenceType();
3097 SourceLocation(), VD,
3098 /*RefersToEnclosingVariableOrCapture=*/false,
3099 Id.getLoc(), ExprType, VK_LValue);
3100}
3101
3104 ArrayRef<Expr *> VarList) {
3105 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3106 CurContext->addDecl(D);
3107 return DeclGroupPtrTy::make(DeclGroupRef(D));
3108 }
3109 return nullptr;
3110}
3111
3112namespace {
3113class LocalVarRefChecker final
3114 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3115 Sema &SemaRef;
3116
3117public:
3118 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3119 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3120 if (VD->hasLocalStorage()) {
3121 SemaRef.Diag(E->getBeginLoc(),
3122 diag::err_omp_local_var_in_threadprivate_init)
3123 << E->getSourceRange();
3124 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3125 << VD << VD->getSourceRange();
3126 return true;
3127 }
3128 }
3129 return false;
3130 }
3131 bool VisitStmt(const Stmt *S) {
3132 for (const Stmt *Child : S->children()) {
3133 if (Child && Visit(Child))
3134 return true;
3135 }
3136 return false;
3137 }
3138 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3139};
3140} // namespace
3141
3145 for (Expr *RefExpr : VarList) {
3146 auto *DE = cast<DeclRefExpr>(RefExpr);
3147 auto *VD = cast<VarDecl>(DE->getDecl());
3148 SourceLocation ILoc = DE->getExprLoc();
3149
3150 // Mark variable as used.
3151 VD->setReferenced();
3152 VD->markUsed(Context);
3153
3154 QualType QType = VD->getType();
3155 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3156 // It will be analyzed later.
3157 Vars.push_back(DE);
3158 continue;
3159 }
3160
3161 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3162 // A threadprivate variable must not have an incomplete type.
3163 if (RequireCompleteType(ILoc, VD->getType(),
3164 diag::err_omp_threadprivate_incomplete_type)) {
3165 continue;
3166 }
3167
3168 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3169 // A threadprivate variable must not have a reference type.
3170 if (VD->getType()->isReferenceType()) {
3171 Diag(ILoc, diag::err_omp_ref_type_arg)
3172 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3173 bool IsDecl =
3175 Diag(VD->getLocation(),
3176 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3177 << VD;
3178 continue;
3179 }
3180
3181 // Check if this is a TLS variable. If TLS is not being supported, produce
3182 // the corresponding diagnostic.
3183 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3184 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3185 getLangOpts().OpenMPUseTLS &&
3186 getASTContext().getTargetInfo().isTLSSupported())) ||
3187 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3188 !VD->isLocalVarDecl())) {
3189 Diag(ILoc, diag::err_omp_var_thread_local)
3190 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3191 bool IsDecl =
3193 Diag(VD->getLocation(),
3194 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3195 << VD;
3196 continue;
3197 }
3198
3199 // Check if initial value of threadprivate variable reference variable with
3200 // local storage (it is not supported by runtime).
3201 if (const Expr *Init = VD->getAnyInitializer()) {
3202 LocalVarRefChecker Checker(*this);
3203 if (Checker.Visit(Init))
3204 continue;
3205 }
3206
3207 Vars.push_back(RefExpr);
3208 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3209 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3210 Context, SourceRange(Loc, Loc)));
3211 if (ASTMutationListener *ML = Context.getASTMutationListener())
3212 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3213 }
3214 OMPThreadPrivateDecl *D = nullptr;
3215 if (!Vars.empty()) {
3216 D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
3217 Vars);
3218 D->setAccess(AS_public);
3219 }
3220 return D;
3221}
3222
3223static OMPAllocateDeclAttr::AllocatorTypeTy
3224getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3225 if (!Allocator)
3226 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3227 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3228 Allocator->isInstantiationDependent() ||
3229 Allocator->containsUnexpandedParameterPack())
3230 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3231 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3232 const Expr *AE = Allocator->IgnoreParenImpCasts();
3233 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3234 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3235 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3236 llvm::FoldingSetNodeID AEId, DAEId;
3237 AE->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3238 DefAllocator->Profile(DAEId, S.getASTContext(), /*Canonical=*/true);
3239 if (AEId == DAEId) {
3240 AllocatorKindRes = AllocatorKind;
3241 break;
3242 }
3243 }
3244 return AllocatorKindRes;
3245}
3246
3248 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3249 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3250 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3251 return false;
3252 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3253 Expr *PrevAllocator = A->getAllocator();
3254 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3255 getAllocatorKind(S, Stack, PrevAllocator);
3256 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3257 if (AllocatorsMatch &&
3258 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3259 Allocator && PrevAllocator) {
3260 const Expr *AE = Allocator->IgnoreParenImpCasts();
3261 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3262 llvm::FoldingSetNodeID AEId, PAEId;
3263 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3264 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3265 AllocatorsMatch = AEId == PAEId;
3266 }
3267 if (!AllocatorsMatch) {
3268 SmallString<256> AllocatorBuffer;
3269 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3270 if (Allocator)
3271 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3272 SmallString<256> PrevAllocatorBuffer;
3273 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3274 if (PrevAllocator)
3275 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3276 S.getPrintingPolicy());
3277
3278 SourceLocation AllocatorLoc =
3279 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3280 SourceRange AllocatorRange =
3281 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3282 SourceLocation PrevAllocatorLoc =
3283 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3284 SourceRange PrevAllocatorRange =
3285 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3286 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3287 << (Allocator ? 1 : 0) << AllocatorStream.str()
3288 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3289 << AllocatorRange;
3290 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3291 << PrevAllocatorRange;
3292 return true;
3293 }
3294 return false;
3295}
3296
3297static void
3299 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3300 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3301 if (VD->hasAttr<OMPAllocateDeclAttr>())
3302 return;
3303 if (Alignment &&
3304 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3305 Alignment->isInstantiationDependent() ||
3306 Alignment->containsUnexpandedParameterPack()))
3307 // Apply later when we have a usable value.
3308 return;
3309 if (Allocator &&
3310 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3311 Allocator->isInstantiationDependent() ||
3312 Allocator->containsUnexpandedParameterPack()))
3313 return;
3314 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3315 Allocator, Alignment, SR);
3316 VD->addAttr(A);
3318 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3319}
3320
3323 ArrayRef<OMPClause *> Clauses,
3324 DeclContext *Owner) {
3325 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3326 Expr *Alignment = nullptr;
3327 Expr *Allocator = nullptr;
3328 if (Clauses.empty()) {
3329 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3330 // allocate directives that appear in a target region must specify an
3331 // allocator clause unless a requires directive with the dynamic_allocators
3332 // clause is present in the same compilation unit.
3333 if (LangOpts.OpenMPIsDevice &&
3334 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3335 targetDiag(Loc, diag::err_expected_allocator_clause);
3336 } else {
3337 for (const OMPClause *C : Clauses)
3338 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3339 Allocator = AC->getAllocator();
3340 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3341 Alignment = AC->getAlignment();
3342 else
3343 llvm_unreachable("Unexpected clause on allocate directive");
3344 }
3345 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3346 getAllocatorKind(*this, DSAStack, Allocator);
3348 for (Expr *RefExpr : VarList) {
3349 auto *DE = cast<DeclRefExpr>(RefExpr);
3350 auto *VD = cast<VarDecl>(DE->getDecl());
3351
3352 // Check if this is a TLS variable or global register.
3353 if (VD->getTLSKind() != VarDecl::TLS_None ||
3354 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3355 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3356 !VD->isLocalVarDecl()))
3357 continue;
3358
3359 // If the used several times in the allocate directive, the same allocator
3360 // must be used.
3361 if (checkPreviousOMPAllocateAttribute(*this, DSAStack, RefExpr, VD,
3362 AllocatorKind, Allocator))
3363 continue;
3364
3365 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3366 // If a list item has a static storage type, the allocator expression in the
3367 // allocator clause must be a constant expression that evaluates to one of
3368 // the predefined memory allocator values.
3369 if (Allocator && VD->hasGlobalStorage()) {
3370 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3371 Diag(Allocator->getExprLoc(),
3372 diag::err_omp_expected_predefined_allocator)
3373 << Allocator->getSourceRange();
3374 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3376 Diag(VD->getLocation(),
3377 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3378 << VD;
3379 continue;
3380 }
3381 }
3382
3383 Vars.push_back(RefExpr);
3384 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3385 DE->getSourceRange());
3386 }
3387 if (Vars.empty())
3388 return nullptr;
3389 if (!Owner)
3390 Owner = getCurLexicalContext();
3391 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3392 D->setAccess(AS_public);
3393 Owner->addDecl(D);
3394 return DeclGroupPtrTy::make(DeclGroupRef(D));
3395}
3396
3399 ArrayRef<OMPClause *> ClauseList) {
3400 OMPRequiresDecl *D = nullptr;
3401 if (!CurContext->isFileContext()) {
3402 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3403 } else {
3404 D = CheckOMPRequiresDecl(Loc, ClauseList);
3405 if (D) {
3406 CurContext->addDecl(D);
3407 DSAStack->addRequiresDecl(D);
3408 }
3409 }
3410 return DeclGroupPtrTy::make(DeclGroupRef(D));
3411}
3412
3414 OpenMPDirectiveKind DKind,
3415 ArrayRef<std::string> Assumptions,
3416 bool SkippedClauses) {
3417 if (!SkippedClauses && Assumptions.empty())
3418 Diag(Loc, diag::err_omp_no_clause_for_directive)
3419 << llvm::omp::getAllAssumeClauseOptions()
3420 << llvm::omp::getOpenMPDirectiveName(DKind);
3421
3422 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3423 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3424 OMPAssumeScoped.push_back(AA);
3425 return;
3426 }
3427
3428 // Global assumes without assumption clauses are ignored.
3429 if (Assumptions.empty())
3430 return;
3431
3432 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3433 "Unexpected omp assumption directive!");
3434 OMPAssumeGlobal.push_back(AA);
3435
3436 // The OMPAssumeGlobal scope above will take care of new declarations but
3437 // we also want to apply the assumption to existing ones, e.g., to
3438 // declarations in included headers. To this end, we traverse all existing
3439 // declaration contexts and annotate function declarations here.
3440 SmallVector<DeclContext *, 8> DeclContexts;
3441 auto *Ctx = CurContext;
3442 while (Ctx->getLexicalParent())
3443 Ctx = Ctx->getLexicalParent();
3444 DeclContexts.push_back(Ctx);
3445 while (!DeclContexts.empty()) {
3446 DeclContext *DC = DeclContexts.pop_back_val();
3447 for (auto *SubDC : DC->decls()) {
3448 if (SubDC->isInvalidDecl())
3449 continue;
3450 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3451 DeclContexts.push_back(CTD->getTemplatedDecl());
3452 llvm::append_range(DeclContexts, CTD->specializations());
3453 continue;
3454 }
3455 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3456 DeclContexts.push_back(DC);
3457 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3458 F->addAttr(AA);
3459 continue;
3460 }
3461 }
3462 }
3463}
3464
3466 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3467 OMPAssumeScoped.pop_back();
3468}
3469
3471 ArrayRef<OMPClause *> ClauseList) {
3472 /// For target specific clauses, the requires directive cannot be
3473 /// specified after the handling of any of the target regions in the
3474 /// current compilation unit.
3475 ArrayRef<SourceLocation> TargetLocations =
3476 DSAStack->getEncounteredTargetLocs();
3477 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3478 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3479 for (const OMPClause *CNew : ClauseList) {
3480 // Check if any of the requires clauses affect target regions.
3481 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3482 isa<OMPUnifiedAddressClause>(CNew) ||
3483 isa<OMPReverseOffloadClause>(CNew) ||
3484 isa<OMPDynamicAllocatorsClause>(CNew)) {
3485 Diag(Loc, diag::err_omp_directive_before_requires)
3486 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3487 for (SourceLocation TargetLoc : TargetLocations) {
3488 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3489 << "target";
3490 }
3491 } else if (!AtomicLoc.isInvalid() &&
3492 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3493 Diag(Loc, diag::err_omp_directive_before_requires)
3494 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3495 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3496 << "atomic";
3497 }
3498 }
3499 }
3500
3501 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3502 return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
3503 ClauseList);
3504 return nullptr;
3505}
3506
3507static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3508 const ValueDecl *D,
3509 const DSAStackTy::DSAVarData &DVar,
3510 bool IsLoopIterVar) {
3511 if (DVar.RefExpr) {
3512 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3513 << getOpenMPClauseName(DVar.CKind);
3514 return;
3515 }
3516 enum {
3517 PDSA_StaticMemberShared,
3518 PDSA_StaticLocalVarShared,
3519 PDSA_LoopIterVarPrivate,
3520 PDSA_LoopIterVarLinear,
3521 PDSA_LoopIterVarLastprivate,
3522 PDSA_ConstVarShared,
3523 PDSA_GlobalVarShared,
3524 PDSA_TaskVarFirstprivate,
3525 PDSA_LocalVarPrivate,
3526 PDSA_Implicit
3527 } Reason = PDSA_Implicit;
3528 bool ReportHint = false;
3529 auto ReportLoc = D->getLocation();
3530 auto *VD = dyn_cast<VarDecl>(D);
3531 if (IsLoopIterVar) {
3532 if (DVar.CKind == OMPC_private)
3533 Reason = PDSA_LoopIterVarPrivate;
3534 else if (DVar.CKind == OMPC_lastprivate)
3535 Reason = PDSA_LoopIterVarLastprivate;
3536 else
3537 Reason = PDSA_LoopIterVarLinear;
3538 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3539 DVar.CKind == OMPC_firstprivate) {
3540 Reason = PDSA_TaskVarFirstprivate;
3541 ReportLoc = DVar.ImplicitDSALoc;
3542 } else if (VD && VD->isStaticLocal())
3543 Reason = PDSA_StaticLocalVarShared;
3544 else if (VD && VD->isStaticDataMember())
3545 Reason = PDSA_StaticMemberShared;
3546 else if (VD && VD->isFileVarDecl())
3547 Reason = PDSA_GlobalVarShared;
3548 else if (D->getType().isConstant(SemaRef.getASTContext()))
3549 Reason = PDSA_ConstVarShared;
3550 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3551 ReportHint = true;
3552 Reason = PDSA_LocalVarPrivate;
3553 }
3554 if (Reason != PDSA_Implicit) {
3555 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3556 << Reason << ReportHint
3557 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3558 } else if (DVar.ImplicitDSALoc.isValid()) {
3559 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3560 << getOpenMPClauseName(DVar.CKind);
3561 }
3562}
3563
3566 bool IsAggregateOrDeclareTarget) {
3568 switch (M) {
3569 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3570 Kind = OMPC_MAP_alloc;
3571 break;
3572 case OMPC_DEFAULTMAP_MODIFIER_to:
3573 Kind = OMPC_MAP_to;
3574 break;
3575 case OMPC_DEFAULTMAP_MODIFIER_from:
3576 Kind = OMPC_MAP_from;
3577 break;
3578 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3579 Kind = OMPC_MAP_tofrom;
3580 break;
3581 case OMPC_DEFAULTMAP_MODIFIER_present:
3582 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3583 // If implicit-behavior is present, each variable referenced in the
3584 // construct in the category specified by variable-category is treated as if
3585 // it had been listed in a map clause with the map-type of alloc and
3586 // map-type-modifier of present.
3587 Kind = OMPC_MAP_alloc;
3588 break;
3589 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3591 llvm_unreachable("Unexpected defaultmap implicit behavior");
3592 case OMPC_DEFAULTMAP_MODIFIER_none:
3593 case OMPC_DEFAULTMAP_MODIFIER_default:
3595 // IsAggregateOrDeclareTarget could be true if:
3596 // 1. the implicit behavior for aggregate is tofrom
3597 // 2. it's a declare target link
3598 if (IsAggregateOrDeclareTarget) {
3599 Kind = OMPC_MAP_tofrom;
3600 break;
3601 }
3602 llvm_unreachable("Unexpected defaultmap implicit behavior");
3603 }
3604 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3605 return Kind;
3606}
3607
3608namespace {
3609class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3610 DSAStackTy *Stack;
3611 Sema &SemaRef;
3612 bool ErrorFound = false;
3613 bool TryCaptureCXXThisMembers = false;
3614 CapturedStmt *CS = nullptr;
3615 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
3616 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3617 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3618 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3620 ImplicitMapModifier[DefaultmapKindNum];
3621 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3622 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3623
3624 void VisitSubCaptures(OMPExecutableDirective *S) {
3625 // Check implicitly captured variables.
3626 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3627 return;
3628 if (S->getDirectiveKind() == OMPD_atomic ||
3629 S->getDirectiveKind() == OMPD_critical ||
3630 S->getDirectiveKind() == OMPD_section ||
3631 S->getDirectiveKind() == OMPD_master ||
3632 S->getDirectiveKind() == OMPD_masked ||
3633 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3634 Visit(S->getAssociatedStmt());
3635 return;
3636 }
3637 visitSubCaptures(S->getInnermostCapturedStmt());
3638 // Try to capture inner this->member references to generate correct mappings
3639 // and diagnostics.
3640 if (TryCaptureCXXThisMembers ||
3641 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3642 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3643 [](const CapturedStmt::Capture &C) {
3644 return C.capturesThis();
3645 }))) {
3646 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3647 TryCaptureCXXThisMembers = true;
3648 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3649 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3650 }
3651 // In tasks firstprivates are not captured anymore, need to analyze them
3652 // explicitly.
3653 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3654 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3655 for (OMPClause *C : S->clauses())
3656 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3657 for (Expr *Ref : FC->varlists())
3658 Visit(Ref);
3659 }
3660 }
3661 }
3662
3663public:
3664 void VisitDeclRefExpr(DeclRefExpr *E) {
3665 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3668 return;
3669 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3670 // Check the datasharing rules for the expressions in the clauses.
3671 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3672 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3673 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3674 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3675 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3676 Visit(CED->getInit());
3677 return;
3678 }
3679 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3680 // Do not analyze internal variables and do not enclose them into
3681 // implicit clauses.
3682 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3683 return;
3684 VD = VD->getCanonicalDecl();
3685 // Skip internally declared variables.
3686 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3687 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3688 !Stack->isImplicitTaskFirstprivate(VD))
3689 return;
3690 // Skip allocators in uses_allocators clauses.
3691 if (Stack->isUsesAllocatorsDecl(VD))
3692 return;
3693
3694 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3695 // Check if the variable has explicit DSA set and stop analysis if it so.
3696 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3697 return;
3698
3699 // Skip internally declared static variables.
3701 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3702 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3703 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3704 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3705 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3706 !Stack->isImplicitTaskFirstprivate(VD))
3707 return;
3708
3709 SourceLocation ELoc = E->getExprLoc();
3710 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3711 // The default(none) clause requires that each variable that is referenced
3712 // in the construct, and does not have a predetermined data-sharing
3713 // attribute, must have its data-sharing attribute explicitly determined
3714 // by being listed in a data-sharing attribute clause.
3715 if (DVar.CKind == OMPC_unknown &&
3716 (Stack->getDefaultDSA() == DSA_none ||
3717 Stack->getDefaultDSA() == DSA_private ||
3718 Stack->getDefaultDSA() == DSA_firstprivate) &&
3719 isImplicitOrExplicitTaskingRegion(DKind) &&
3720 VarsWithInheritedDSA.count(VD) == 0) {
3721 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3722 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3723 Stack->getDefaultDSA() == DSA_private)) {
3724 DSAStackTy::DSAVarData DVar =
3725 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3726 InheritedDSA = DVar.CKind == OMPC_unknown;
3727 }
3728 if (InheritedDSA)
3729 VarsWithInheritedDSA[VD] = E;
3730 if (Stack->getDefaultDSA() == DSA_none)
3731 return;
3732 }
3733
3734 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3735 // If implicit-behavior is none, each variable referenced in the
3736 // construct that does not have a predetermined data-sharing attribute
3737 // and does not appear in a to or link clause on a declare target
3738 // directive must be listed in a data-mapping attribute clause, a
3739 // data-sharing attribute clause (including a data-sharing attribute
3740 // clause on a combined construct where target. is one of the
3741 // constituent constructs), or an is_device_ptr clause.
3742 OpenMPDefaultmapClauseKind ClauseKind =
3744 if (SemaRef.getLangOpts().OpenMP >= 50) {
3745 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3746 OMPC_DEFAULTMAP_MODIFIER_none;
3747 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3748 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3749 // Only check for data-mapping attribute and is_device_ptr here
3750 // since we have already make sure that the declaration does not
3751 // have a data-sharing attribute above
3752 if (!Stack->checkMappableExprComponentListsForDecl(
3753 VD, /*CurrentRegionOnly=*/true,
3755 MapExprComponents,
3757 auto MI = MapExprComponents.rbegin();
3758 auto ME = MapExprComponents.rend();
3759 return MI != ME && MI->getAssociatedDeclaration() == VD;
3760 })) {
3761 VarsWithInheritedDSA[VD] = E;
3762 return;
3763 }
3764 }
3765 }
3766 if (SemaRef.getLangOpts().OpenMP > 50) {
3767 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3768 OMPC_DEFAULTMAP_MODIFIER_present;
3769 if (IsModifierPresent) {
3770 if (llvm::find(ImplicitMapModifier[ClauseKind],
3771 OMPC_MAP_MODIFIER_present) ==
3772 std::end(ImplicitMapModifier[ClauseKind])) {
3773 ImplicitMapModifier[ClauseKind].push_back(
3774 OMPC_MAP_MODIFIER_present);
3775 }
3776 }
3777 }
3778
3780 !Stack->isLoopControlVariable(VD).first) {
3781 if (!Stack->checkMappableExprComponentListsForDecl(
3782 VD, /*CurrentRegionOnly=*/true,
3784 StackComponents,
3786 if (SemaRef.LangOpts.OpenMP >= 50)
3787 return !StackComponents.empty();
3788 // Variable is used if it has been marked as an array, array
3789 // section, array shaping or the variable iself.
3790 return StackComponents.size() == 1 ||
3791 std::all_of(
3792 std::next(StackComponents.rbegin()),
3793 StackComponents.rend(),
3794 [](const OMPClauseMappableExprCommon::
3795 MappableComponent &MC) {
3796 return MC.getAssociatedDeclaration() ==
3797 nullptr &&
3798 (isa<OMPArraySectionExpr>(
3799 MC.getAssociatedExpression()) ||
3800 isa<OMPArrayShapingExpr>(
3801 MC.getAssociatedExpression()) ||
3802 isa<ArraySubscriptExpr>(
3803 MC.getAssociatedExpression()));
3804 });
3805 })) {
3806 bool IsFirstprivate = false;
3807 // By default lambdas are captured as firstprivates.
3808 if (const auto *RD =
3810 IsFirstprivate = RD->isLambda();
3811 IsFirstprivate =
3812 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3813 if (IsFirstprivate) {
3814 ImplicitFirstprivate.emplace_back(E);
3815 } else {
3817 Stack->getDefaultmapModifier(ClauseKind);
3819 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3820 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3821 }
3822 return;
3823 }
3824 }
3825
3826 // OpenMP [2.9.3.6, Restrictions, p.2]
3827 // A list item that appears in a reduction clause of the innermost
3828 // enclosing worksharing or parallel construct may not be accessed in an
3829 // explicit task.
3830 DVar = Stack->hasInnermostDSA(
3831 VD,
3832 [](OpenMPClauseKind C, bool AppliedToPointee) {
3833 return C == OMPC_reduction && !AppliedToPointee;
3834 },
3835 [](OpenMPDirectiveKind K) {
3836 return isOpenMPParallelDirective(K) ||
3838 },
3839 /*FromParent=*/true);
3840 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3841 ErrorFound = true;
3842 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3843 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3844 return;
3845 }
3846
3847 // Define implicit data-sharing attributes for task.
3848 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3849 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3850 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3851 DVar.CKind == OMPC_firstprivate) ||
3852 (Stack->getDefaultDSA() == DSA_private &&
3853 DVar.CKind == OMPC_private)) &&
3854 !DVar.RefExpr)) &&
3855 !Stack->isLoopControlVariable(VD).first) {
3856 if (Stack->getDefaultDSA() == DSA_private)
3857 ImplicitPrivate.push_back(E);
3858 else
3859 ImplicitFirstprivate.push_back(E);
3860 return;
3861 }
3862
3863 // Store implicitly used globals with declare target link for parent
3864 // target.
3865 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3866 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3867 Stack->addToParentTargetRegionLinkGlobals(E);
3868 return;
3869 }
3870 }
3871 }
3872 void VisitMemberExpr(MemberExpr *E) {
3873 if (E->isTypeDependent() || E->isValueDependent() ||
3875 return;
3876 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3877 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3878 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3879 if (!FD)
3880 return;
3881 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3882 // Check if the variable has explicit DSA set and stop analysis if it
3883 // so.
3884 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3885 return;
3886
3888 !Stack->isLoopControlVariable(FD).first &&
3889 !Stack->checkMappableExprComponentListsForDecl(
3890 FD, /*CurrentRegionOnly=*/true,
3892 StackComponents,
3894 return isa<CXXThisExpr>(
3895 cast<MemberExpr>(
3896 StackComponents.back().getAssociatedExpression())
3897 ->getBase()
3898 ->IgnoreParens());
3899 })) {
3900 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3901 // A bit-field cannot appear in a map clause.
3902 //
3903 if (FD->isBitField())
3904 return;
3905
3906 // Check to see if the member expression is referencing a class that
3907 // has already been explicitly mapped
3908 if (Stack->isClassPreviouslyMapped(TE->getType()))
3909 return;
3910
3912 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3913 OpenMPDefaultmapClauseKind ClauseKind =
3916 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3917 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3918 return;
3919 }
3920
3921 SourceLocation ELoc = E->getExprLoc();
3922 // OpenMP [2.9.3.6, Restrictions, p.2]
3923 // A list item that appears in a reduction clause of the innermost
3924 // enclosing worksharing or parallel construct may not be accessed in
3925 // an explicit task.
3926 DVar = Stack->hasInnermostDSA(
3927 FD,
3928 [](OpenMPClauseKind C, bool AppliedToPointee) {
3929 return C == OMPC_reduction && !AppliedToPointee;
3930 },
3931 [](OpenMPDirectiveKind K) {
3932 return isOpenMPParallelDirective(K) ||
3934 },
3935 /*FromParent=*/true);
3936 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3937 ErrorFound = true;
3938 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3939 reportOriginalDsa(SemaRef, Stack, FD, DVar);
3940 return;
3941 }
3942
3943 // Define implicit data-sharing attributes for task.
3944 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
3945 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
3946 !Stack->isLoopControlVariable(FD).first) {
3947 // Check if there is a captured expression for the current field in the
3948 // region. Do not mark it as firstprivate unless there is no captured
3949 // expression.
3950 // TODO: try to make it firstprivate.
3951 if (DVar.CKind != OMPC_unknown)
3952 ImplicitFirstprivate.push_back(E);
3953 }
3954 return;
3955 }
3958 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
3959 Stack->getCurrentDirective(),
3960 /*NoDiagnose=*/true))
3961 return;
3962 const auto *VD = cast<ValueDecl>(
3963 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
3964 if (!Stack->checkMappableExprComponentListsForDecl(
3965 VD, /*CurrentRegionOnly=*/true,
3966 [&CurComponents](
3968 StackComponents,
3970 auto CCI = CurComponents.rbegin();
3971 auto CCE = CurComponents.rend();
3972 for (const auto &SC : llvm::reverse(StackComponents)) {
3973 // Do both expressions have the same kind?
3974 if (CCI->getAssociatedExpression()->getStmtClass() !=
3975 SC.getAssociatedExpression()->getStmtClass())
3976 if (!((isa<OMPArraySectionExpr>(
3977 SC.getAssociatedExpression()) ||
3978 isa<OMPArrayShapingExpr>(
3979 SC.getAssociatedExpression())) &&
3980 isa<ArraySubscriptExpr>(
3981 CCI->getAssociatedExpression())))
3982 return false;
3983
3984 const Decl *CCD = CCI->getAssociatedDeclaration();
3985 const Decl *SCD = SC.getAssociatedDeclaration();
3986 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
3987 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
3988 if (SCD != CCD)
3989 return false;
3990 std::advance(CCI, 1);
3991 if (CCI == CCE)
3992 break;
3993 }
3994 return true;
3995 })) {
3996 Visit(E->getBase());
3997 }
3998 } else if (!TryCaptureCXXThisMembers) {
3999 Visit(E->getBase());
4000 }
4001 }
4002 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4003 for (OMPClause *C : S->clauses()) {
4004 // Skip analysis of arguments of private clauses for task|target
4005 // directives.
4006 if (isa_and_nonnull<OMPPrivateClause>(C))
4007 continue;
4008 // Skip analysis of arguments of implicitly defined firstprivate clause
4009 // for task|target directives.
4010 // Skip analysis of arguments of implicitly defined map clause for target
4011 // directives.
4012 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4013 C->isImplicit() &&
4014 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4015 for (Stmt *CC : C->children()) {
4016 if (CC)
4017 Visit(CC);
4018 }
4019 }
4020 }
4021 // Check implicitly captured variables.
4022 VisitSubCaptures(S);
4023 }
4024
4025 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4026 // Loop transformation directives do not introduce data sharing
4027 VisitStmt(S);
4028 }
4029
4030 void VisitCallExpr(CallExpr *S) {
4031 for (Stmt *C : S->arguments()) {
4032 if (C) {
4033 // Check implicitly captured variables in the task-based directives to
4034 // check if they must be firstprivatized.
4035 Visit(C);
4036 }
4037 }
4038 if (Expr *Callee = S->getCallee())
4039 if (auto *CE = dyn_cast<MemberExpr>(Callee->IgnoreParenImpCasts()))
4040 Visit(CE->getBase());
4041 }
4042 void VisitStmt(Stmt *S) {
4043 for (Stmt *C : S->children()) {
4044 if (C) {
4045 // Check implicitly captured variables in the task-based directives to
4046 // check if they must be firstprivatized.
4047 Visit(C);
4048 }
4049 }
4050 }
4051
4052 void visitSubCaptures(CapturedStmt *S) {
4053 for (const CapturedStmt::Capture &Cap : S->captures()) {
4054 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4055 continue;
4056 VarDecl *VD = Cap.getCapturedVar();
4057 // Do not try to map the variable if it or its sub-component was mapped
4058 // already.
4059 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4060 Stack->checkMappableExprComponentListsForDecl(
4061 VD, /*CurrentRegionOnly=*/true,
4063 OpenMPClauseKind) { return true; }))
4064 continue;
4066 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4067 Cap.getLocation(), /*RefersToCapture=*/true);
4068 Visit(DRE);
4069 }
4070 }
4071 bool isErrorFound() const { return ErrorFound; }
4072 ArrayRef<Expr *> getImplicitFirstprivate() const {
4073 return ImplicitFirstprivate;
4074 }
4075 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4077 OpenMPMapClauseKind MK) const {
4078 return ImplicitMap[DK][MK];
4079 }
4081 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4082 return ImplicitMapModifier[Kind];
4083 }
4084 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4085 return VarsWithInheritedDSA;
4086 }
4087
4088 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4089 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4090 // Process declare target link variables for the target directives.
4091 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4092 for (DeclRefExpr *E : Stack->getLinkGlobals())
4093 Visit(E);
4094 }
4095 }
4096};
4097} // namespace
4098
4099static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4100 OpenMPDirectiveKind DKind,
4101 bool ScopeEntry) {
4104 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4105 if (isOpenMPTeamsDirective(DKind))
4106 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4107 if (isOpenMPParallelDirective(DKind))
4108 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4110 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4111 if (isOpenMPSimdDirective(DKind))
4112 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4113 Stack->handleConstructTrait(Traits, ScopeEntry);
4114}
4115
4117 switch (DKind) {
4118 case OMPD_parallel:
4119 case OMPD_parallel_for:
4120 case OMPD_parallel_for_simd:
4121 case OMPD_parallel_sections:
4122 case OMPD_parallel_master:
4123 case OMPD_parallel_masked:
4124 case OMPD_parallel_loop:
4125 case OMPD_teams:
4126 case OMPD_teams_distribute:
4127 case OMPD_teams_distribute_simd: {
4128 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4129 QualType KmpInt32PtrTy =
4130 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4131 Sema::CapturedParamNameType Params[] = {
4132 std::make_pair(".global_tid.", KmpInt32PtrTy),
4133 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4134 std::make_pair(StringRef(), QualType()) // __context with shared vars
4135 };
4136 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4137 Params);
4138 break;
4139 }
4140 case OMPD_target_teams:
4141 case OMPD_target_parallel:
4142 case OMPD_target_parallel_for:
4143 case OMPD_target_parallel_for_simd:
4144 case OMPD_target_teams_loop:
4145 case OMPD_target_parallel_loop:
4146 case OMPD_target_teams_distribute:
4147 case OMPD_target_teams_distribute_simd: {
4148 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4149 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4150 QualType KmpInt32PtrTy =
4151 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4152 QualType Args[] = {VoidPtrTy};
4154 EPI.Variadic = true;
4155 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4156 Sema::CapturedParamNameType Params[] = {
4157 std::make_pair(".global_tid.", KmpInt32Ty),
4158 std::make_pair(".part_id.", KmpInt32PtrTy),
4159 std::make_pair(".privates.", VoidPtrTy),
4160 std::make_pair(
4161 ".copy_fn.",
4162 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4163 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4164 std::make_pair(StringRef(), QualType()) // __context with shared vars
4165 };
4166 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4167 Params, /*OpenMPCaptureLevel=*/0);
4168 // Mark this captured region as inlined, because we don't use outlined
4169 // function directly.
4170 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4171 AlwaysInlineAttr::CreateImplicit(
4173 AlwaysInlineAttr::Keyword_forceinline));
4174 Sema::CapturedParamNameType ParamsTarget[] = {
4175 std::make_pair(StringRef(), QualType()) // __context with shared vars
4176 };
4177 // Start a captured region for 'target' with no implicit parameters.
4178 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4179 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4180 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4181 std::make_pair(".global_tid.", KmpInt32PtrTy),
4182 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4183 std::make_pair(StringRef(), QualType()) // __context with shared vars
4184 };
4185 // Start a captured region for 'teams' or 'parallel'. Both regions have
4186 // the same implicit parameters.
4187 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4188 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4189 break;
4190 }
4191 case OMPD_target:
4192 case OMPD_target_simd: {
4193 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4194 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4195 QualType KmpInt32PtrTy =
4196 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4197 QualType Args[] = {VoidPtrTy};
4199 EPI.Variadic = true;
4200 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4201 Sema::CapturedParamNameType Params[] = {
4202 std::make_pair(".global_tid.", KmpInt32Ty),
4203 std::make_pair(".part_id.", KmpInt32PtrTy),
4204 std::make_pair(".privates.", VoidPtrTy),
4205 std::make_pair(
4206 ".copy_fn.",
4207 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4208 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4209 std::make_pair(StringRef(), QualType()) // __context with shared vars
4210 };
4211 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4212 Params, /*OpenMPCaptureLevel=*/0);
4213 // Mark this captured region as inlined, because we don't use outlined
4214 // function directly.
4215 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4216 AlwaysInlineAttr::CreateImplicit(
4218 AlwaysInlineAttr::Keyword_forceinline));
4219 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4220 std::make_pair(StringRef(), QualType()),
4221 /*OpenMPCaptureLevel=*/1);
4222 break;
4223 }
4224 case OMPD_atomic:
4225 case OMPD_critical:
4226 case OMPD_section:
4227 case OMPD_master:
4228 case OMPD_masked:
4229 case OMPD_tile:
4230 case OMPD_unroll:
4231 break;
4232 case OMPD_loop:
4233 // TODO: 'loop' may require additional parameters depending on the binding.
4234 // Treat similar to OMPD_simd/OMPD_for for now.
4235 case OMPD_simd:
4236 case OMPD_for:
4237 case OMPD_for_simd:
4238 case OMPD_sections:
4239 case OMPD_single:
4240 case OMPD_taskgroup:
4241 case OMPD_distribute:
4242 case OMPD_distribute_simd:
4243 case OMPD_ordered:
4244 case OMPD_target_data:
4245 case OMPD_dispatch: {
4246 Sema::CapturedParamNameType Params[] = {
4247 std::make_pair(StringRef(), QualType()) // __context with shared vars
4248 };
4249 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4250 Params);
4251 break;
4252 }
4253 case OMPD_task: {
4254 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4255 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4256 QualType KmpInt32PtrTy =
4257 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4258 QualType Args[] = {VoidPtrTy};
4260 EPI.Variadic = true;
4261 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4262 Sema::CapturedParamNameType Params[] = {
4263 std::make_pair(".global_tid.", KmpInt32Ty),
4264 std::make_pair(".part_id.", KmpInt32PtrTy),
4265 std::make_pair(".privates.", VoidPtrTy),
4266 std::make_pair(
4267 ".copy_fn.",
4268 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4269 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4270 std::make_pair(StringRef(), QualType()) // __context with shared vars
4271 };
4272 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4273 Params);
4274 // Mark this captured region as inlined, because we don't use outlined
4275 // function directly.
4276 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4277 AlwaysInlineAttr::CreateImplicit(
4279 AlwaysInlineAttr::Keyword_forceinline));
4280 break;
4281 }
4282 case OMPD_taskloop:
4283 case OMPD_taskloop_simd:
4284 case OMPD_master_taskloop:
4285 case OMPD_masked_taskloop:
4286 case OMPD_masked_taskloop_simd:
4287 case OMPD_master_taskloop_simd: {
4288 QualType KmpInt32Ty =
4289 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4290 .withConst();
4291 QualType KmpUInt64Ty =
4292 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4293 .withConst();
4294 QualType KmpInt64Ty =
4295 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4296 .withConst();
4297 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4298 QualType KmpInt32PtrTy =
4299 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4300 QualType Args[] = {VoidPtrTy};
4302 EPI.Variadic = true;
4303 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4304 Sema::CapturedParamNameType Params[] = {
4305 std::make_pair(".global_tid.", KmpInt32Ty),
4306 std::make_pair(".part_id.", KmpInt32PtrTy),
4307 std::make_pair(".privates.", VoidPtrTy),
4308 std::make_pair(
4309 ".copy_fn.",
4310 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4311 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4312 std::make_pair(".lb.", KmpUInt64Ty),
4313 std::make_pair(".ub.", KmpUInt64Ty),
4314 std::make_pair(".st.", KmpInt64Ty),
4315 std::make_pair(".liter.", KmpInt32Ty),
4316 std::make_pair(".reductions.", VoidPtrTy),
4317 std::make_pair(StringRef(), QualType()) // __context with shared vars
4318 };
4319 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4320 Params);
4321 // Mark this captured region as inlined, because we don't use outlined
4322 // function directly.
4323 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4324 AlwaysInlineAttr::CreateImplicit(
4326 AlwaysInlineAttr::Keyword_forceinline));
4327 break;
4328 }
4329 case OMPD_parallel_masked_taskloop:
4330 case OMPD_parallel_masked_taskloop_simd:
4331 case OMPD_parallel_master_taskloop:
4332 case OMPD_parallel_master_taskloop_simd: {
4333 QualType KmpInt32Ty =
4334 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4335 .withConst();
4336 QualType KmpUInt64Ty =
4337 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4338 .withConst();
4339 QualType KmpInt64Ty =
4340 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4341 .withConst();
4342 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4343 QualType KmpInt32PtrTy =
4344 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4345 Sema::CapturedParamNameType ParamsParallel[] = {
4346 std::make_pair(".global_tid.", KmpInt32PtrTy),
4347 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4348 std::make_pair(StringRef(), QualType()) // __context with shared vars
4349 };
4350 // Start a captured region for 'parallel'.
4351 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4352 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4353 QualType Args[] = {VoidPtrTy};
4355 EPI.Variadic = true;
4356 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4357 Sema::CapturedParamNameType Params[] = {
4358 std::make_pair(".global_tid.", KmpInt32Ty),
4359 std::make_pair(".part_id.", KmpInt32PtrTy),
4360 std::make_pair(".privates.", VoidPtrTy),
4361 std::make_pair(
4362 ".copy_fn.",
4363 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4364 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4365 std::make_pair(".lb.", KmpUInt64Ty),
4366 std::make_pair(".ub.", KmpUInt64Ty),
4367 std::make_pair(".st.", KmpInt64Ty),
4368 std::make_pair(".liter.", KmpInt32Ty),
4369 std::make_pair(".reductions.", VoidPtrTy),
4370 std::make_pair(StringRef(), QualType()) // __context with shared vars
4371 };
4372 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4373 Params, /*OpenMPCaptureLevel=*/1);
4374 // Mark this captured region as inlined, because we don't use outlined
4375 // function directly.
4376 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4377 AlwaysInlineAttr::CreateImplicit(
4379 AlwaysInlineAttr::Keyword_forceinline));
4380 break;
4381 }
4382 case OMPD_distribute_parallel_for_simd:
4383 case OMPD_distribute_parallel_for: {
4384 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4385 QualType KmpInt32PtrTy =
4386 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4387 Sema::CapturedParamNameType Params[] = {
4388 std::make_pair(".global_tid.", KmpInt32PtrTy),
4389 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4390 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4391 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4392 std::make_pair(StringRef(), QualType()) // __context with shared vars
4393 };
4394 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4395 Params);
4396 break;
4397 }
4398 case OMPD_target_teams_distribute_parallel_for:
4399 case OMPD_target_teams_distribute_parallel_for_simd: {
4400 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4401 QualType KmpInt32PtrTy =
4402 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4403 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4404
4405 QualType Args[] = {VoidPtrTy};
4407 EPI.Variadic = true;
4408 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4409 Sema::CapturedParamNameType Params[] = {
4410 std::make_pair(".global_tid.", KmpInt32Ty),
4411 std::make_pair(".part_id.", KmpInt32PtrTy),
4412 std::make_pair(".privates.", VoidPtrTy),
4413 std::make_pair(
4414 ".copy_fn.",
4415 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4416 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4417 std::make_pair(StringRef(), QualType()) // __context with shared vars
4418 };
4419 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4420 Params, /*OpenMPCaptureLevel=*/0);
4421 // Mark this captured region as inlined, because we don't use outlined
4422 // function directly.
4423 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4424 AlwaysInlineAttr::CreateImplicit(
4426 AlwaysInlineAttr::Keyword_forceinline));
4427 Sema::CapturedParamNameType ParamsTarget[] = {
4428 std::make_pair(StringRef(), QualType()) // __context with shared vars
4429 };
4430 // Start a captured region for 'target' with no implicit parameters.
4431 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4432 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4433
4434 Sema::CapturedParamNameType ParamsTeams[] = {
4435 std::make_pair(".global_tid.", KmpInt32PtrTy),
4436 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4437 std::make_pair(StringRef(), QualType()) // __context with shared vars
4438 };
4439 // Start a captured region for 'target' with no implicit parameters.
4440 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4441 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4442
4443 Sema::CapturedParamNameType ParamsParallel[] = {
4444 std::make_pair(".global_tid.", KmpInt32PtrTy),
4445 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4446 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4447 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4448 std::make_pair(StringRef(), QualType()) // __context with shared vars
4449 };
4450 // Start a captured region for 'teams' or 'parallel'. Both regions have
4451 // the same implicit parameters.
4452 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4453 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4454 break;
4455 }
4456
4457 case OMPD_teams_loop: {
4458 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4459 QualType KmpInt32PtrTy =
4460 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4461
4462 Sema::CapturedParamNameType ParamsTeams[] = {
4463 std::make_pair(".global_tid.", KmpInt32PtrTy),
4464 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4465 std::make_pair(StringRef(), QualType()) // __context with shared vars
4466 };
4467 // Start a captured region for 'teams'.
4468 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4469 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4470 break;
4471 }
4472
4473 case OMPD_teams_distribute_parallel_for:
4474 case OMPD_teams_distribute_parallel_for_simd: {
4475 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4476 QualType KmpInt32PtrTy =
4477 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4478
4479 Sema::CapturedParamNameType ParamsTeams[] = {
4480 std::make_pair(".global_tid.", KmpInt32PtrTy),
4481 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4482 std::make_pair(StringRef(), QualType()) // __context with shared vars
4483 };
4484 // Start a captured region for 'target' with no implicit parameters.
4485 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4486 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4487
4488 Sema::CapturedParamNameType ParamsParallel[] = {
4489 std::make_pair(".global_tid.", KmpInt32PtrTy),
4490 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4491 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4492 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4493 std::make_pair(StringRef(), QualType()) // __context with shared vars
4494 };
4495 // Start a captured region for 'teams' or 'parallel'. Both regions have
4496 // the same implicit parameters.
4497 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4498 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4499 break;
4500 }
4501 case OMPD_target_update:
4502 case OMPD_target_enter_data:
4503 case OMPD_target_exit_data: {
4504 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4505 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4506 QualType KmpInt32PtrTy =
4507 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4508 QualType Args[] = {VoidPtrTy};
4510 EPI.Variadic = true;
4511 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4512 Sema::CapturedParamNameType Params[] = {
4513 std::make_pair(".global_tid.", KmpInt32Ty),
4514 std::make_pair(".part_id.", KmpInt32PtrTy),
4515 std::make_pair(".privates.", VoidPtrTy),
4516 std::make_pair(
4517 ".copy_fn.",
4518 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4519 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4520 std::make_pair(StringRef(), QualType()) // __context with shared vars
4521 };
4522 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4523 Params);
4524 // Mark this captured region as inlined, because we don't use outlined
4525 // function directly.
4526 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4527 AlwaysInlineAttr::CreateImplicit(
4529 AlwaysInlineAttr::Keyword_forceinline));
4530 break;
4531 }
4532 case OMPD_threadprivate:
4533 case OMPD_allocate:
4534 case OMPD_taskyield:
4535 case OMPD_barrier:
4536 case OMPD_taskwait:
4537 case OMPD_cancellation_point:
4538 case OMPD_cancel:
4539 case OMPD_flush:
4540 case OMPD_depobj:
4541 case OMPD_scan:
4542 case OMPD_declare_reduction:
4543 case OMPD_declare_mapper:
4544 case OMPD_declare_simd:
4545 case OMPD_declare_target:
4546 case OMPD_end_declare_target:
4547 case OMPD_requires:
4548 case OMPD_declare_variant:
4549 case OMPD_begin_declare_variant:
4550 case OMPD_end_declare_variant:
4551 case OMPD_metadirective:
4552 llvm_unreachable("OpenMP Directive is not allowed");
4553 case OMPD_unknown:
4554 default:
4555 llvm_unreachable("Unknown OpenMP directive");
4556 }
4557 DSAStack->setContext(CurContext);
4558 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4559}
4560
4561int Sema::getNumberOfConstructScopes(unsigned Level) const {
4562 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4563}
4564
4567 getOpenMPCaptureRegions(CaptureRegions, DKind);
4568 return CaptureRegions.size();
4569}
4570
4572 Expr *CaptureExpr, bool WithInit,
4573 DeclContext *CurContext,
4574 bool AsExpression) {
4575 assert(CaptureExpr);
4576 ASTContext &C = S.getASTContext();
4577 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4578 QualType Ty = Init->getType();
4579 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4580 if (S.getLangOpts().CPlusPlus) {
4581 Ty = C.getLValueReferenceType(Ty);
4582 } else {
4583 Ty = C.getPointerType(Ty);
4584 ExprResult Res =
4585 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4586 if (!Res.isUsable())
4587 return nullptr;
4588 Init = Res.get();
4589 }
4590 WithInit = true;
4591 }
4592 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4593 CaptureExpr->getBeginLoc());
4594 if (!WithInit)
4595 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4596 CurContext->addHiddenDecl(CED);
4598 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4599 return CED;
4600}
4601
4602static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4603 bool WithInit) {
4605 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4607 else
4608 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4609 S.CurContext,
4610 /*AsExpression=*/false);
4611 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4612 CaptureExpr->getExprLoc());
4613}
4614
4615static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) {
4616 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4617 if (!Ref) {
4619 S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr,
4620 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4621 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4622 CaptureExpr->getExprLoc());
4623 }
4624 ExprResult Res = Ref;
4625 if (!S.getLangOpts().CPlusPlus &&
4626 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4627 Ref->getType()->isPointerType()) {
4628 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4629 if (!Res.isUsable())
4630 return ExprError();
4631 }
4632 return S.DefaultLvalueConversion(Res.get());
4633}
4634
4635namespace {
4636// OpenMP directives parsed in this section are represented as a
4637// CapturedStatement with an associated statement. If a syntax error
4638// is detected during the parsing of the associated statement, the
4639// compiler must abort processing and close the CapturedStatement.
4640//
4641// Combined directives such as 'target parallel' have more than one
4642// nested CapturedStatements. This RAII ensures that we unwind out
4643// of all the nested CapturedStatements when an error is found.
4644class CaptureRegionUnwinderRAII {
4645private:
4646 Sema &S;
4647 bool &ErrorFound;
4648 OpenMPDirectiveKind DKind = OMPD_unknown;
4649
4650public:
4651 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4652 OpenMPDirectiveKind DKind)
4653 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4654 ~CaptureRegionUnwinderRAII() {
4655 if (ErrorFound) {
4656 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4657 while (--ThisCaptureLevel >= 0)
4659 }
4660 }
4661};
4662} // namespace
4663
4665 // Capture variables captured by reference in lambdas for target-based
4666 // directives.
4667 if (!CurContext->isDependentContext() &&
4668 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4670 DSAStack->getCurrentDirective()))) {
4671 QualType Type = V->getType();
4672 if (const auto *RD = Type.getCanonicalType()
4673 .getNonReferenceType()
4674 ->getAsCXXRecordDecl()) {
4675 bool SavedForceCaptureByReferenceInTargetExecutable =
4676 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4677 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4678 /*V=*/true);
4679 if (RD->isLambda()) {
4680 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
4681 FieldDecl *ThisCapture;
4682 RD->getCaptureFields(Captures, ThisCapture);
4683 for (const LambdaCapture &LC : RD->captures()) {
4684 if (LC.getCaptureKind() == LCK_ByRef) {
4685 VarDecl *VD = LC.getCapturedVar();
4686 DeclContext *VDC = VD->getDeclContext();
4687 if (!VDC->Encloses(CurContext))
4688 continue;
4689 MarkVariableReferenced(LC.getLocation(), VD);
4690 } else if (LC.getCaptureKind() == LCK_This) {
4691 QualType ThisTy = getCurrentThisType();
4692 if (!ThisTy.isNull() &&
4693 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4694 CheckCXXThisCapture(LC.getLocation());
4695 }
4696 }
4697 }
4698 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4699 SavedForceCaptureByReferenceInTargetExecutable);
4700 }
4701 }
4702}
4703
4705 const ArrayRef<OMPClause *> Clauses) {
4706 const OMPOrderedClause *Ordered = nullptr;
4707 const OMPOrderClause *Order = nullptr;
4708
4709 for (const OMPClause *Clause : Clauses) {
4710 if (Clause->getClauseKind() == OMPC_ordered)
4711 Ordered = cast<OMPOrderedClause>(Clause);
4712 else if (Clause->getClauseKind() == OMPC_order) {
4713 Order = cast<OMPOrderClause>(Clause);
4714 if (Order->getKind() != OMPC_ORDER_concurrent)
4715 Order = nullptr;
4716 }
4717 if (Ordered && Order)
4718 break;
4719 }
4720
4721 if (Ordered && Order) {
4722 S.Diag(Order->getKindKwLoc(),
4723 diag::err_omp_simple_clause_incompatible_with_ordered)
4724 << getOpenMPClauseName(OMPC_order)
4725 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4726 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4727 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4728 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4729 return true;
4730 }
4731 return false;
4732}
4733
4735 ArrayRef<OMPClause *> Clauses) {
4737 /* ScopeEntry */ false);
4738 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4739 DSAStack->getCurrentDirective() == OMPD_critical ||
4740 DSAStack->getCurrentDirective() == OMPD_section ||
4741 DSAStack->getCurrentDirective() == OMPD_master ||
4742 DSAStack->getCurrentDirective() == OMPD_masked)
4743 return S;
4744
4745 bool ErrorFound = false;
4746 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4747 *this, ErrorFound, DSAStack->getCurrentDirective());
4748 if (!S.isUsable()) {
4749 ErrorFound = true;
4750 return StmtError();
4751 }
4752
4754 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4755 OMPOrderedClause *OC = nullptr;
4756 OMPScheduleClause *SC = nullptr;
4759 // This is required for proper codegen.
4760 for (OMPClause *Clause : Clauses) {
4761 if (!LangOpts.OpenMPSimd &&
4762 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4763 DSAStack->getCurrentDirective() == OMPD_target) &&
4764 Clause->getClauseKind() == OMPC_in_reduction) {
4765 // Capture taskgroup task_reduction descriptors inside the tasking regions
4766 // with the corresponding in_reduction items.
4767 auto *IRC = cast<OMPInReductionClause>(Clause);
4768 for (Expr *E : IRC->taskgroup_descriptors())
4769 if (E)
4770 MarkDeclarationsReferencedInExpr(E);
4771 }
4772 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4773 Clause->getClauseKind() == OMPC_copyprivate ||
4774 (getLangOpts().OpenMPUseTLS &&
4775 getASTContext().getTargetInfo().isTLSSupported() &&
4776 Clause->getClauseKind() == OMPC_copyin)) {
4777 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4778 // Mark all variables in private list clauses as used in inner region.
4779 for (Stmt *VarRef : Clause->children()) {
4780 if (auto *E = cast_or_null<Expr>(VarRef)) {
4781 MarkDeclarationsReferencedInExpr(E);
4782 }
4783 }
4784 DSAStack->setForceVarCapturing(/*V=*/false);
4786 DSAStack->getCurrentDirective())) {
4787 assert(CaptureRegions.empty() &&
4788 "No captured regions in loop transformation directives.");
4789 } else if (CaptureRegions.size() > 1 ||
4790 CaptureRegions.back() != OMPD_unknown) {
4791 if (auto *C = OMPClauseWithPreInit::get(Clause))
4792 PICs.push_back(C);
4793 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4794 if (Expr *E = C->getPostUpdateExpr())
4795 MarkDeclarationsReferencedInExpr(E);
4796 }
4797 }
4798 if (Clause->getClauseKind() == OMPC_schedule)
4799 SC = cast<OMPScheduleClause>(Clause);
4800 else if (Clause->getClauseKind() == OMPC_ordered)
4801 OC = cast<OMPOrderedClause>(Clause);
4802 else if (Clause->getClauseKind() == OMPC_linear)
4803 LCs.push_back(cast<OMPLinearClause>(Clause));
4804 }
4805 // Capture allocator expressions if used.
4806 for (Expr *E : DSAStack->getInnerAllocators())
4807 MarkDeclarationsReferencedInExpr(E);
4808 // OpenMP, 2.7.1 Loop Construct, Restrictions
4809 // The nonmonotonic modifier cannot be specified if an ordered clause is
4810 // specified.
4811 if (SC &&
4812 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4814 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4815 OC) {
4816 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4819 diag::err_omp_simple_clause_incompatible_with_ordered)
4820 << getOpenMPClauseName(OMPC_schedule)
4821 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4822 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4823 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4824 ErrorFound = true;
4825 }
4826 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4827 // If an order(concurrent) clause is present, an ordered clause may not appear
4828 // on the same directive.
4829 if (checkOrderedOrderSpecified(*this, Clauses))
4830 ErrorFound = true;
4831 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4832 for (const OMPLinearClause *C : LCs) {
4833 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4834 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4835 }
4836 ErrorFound = true;
4837 }
4838 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4839 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4840 OC->getNumForLoops()) {
4841 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4842 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4843 ErrorFound = true;
4844 }
4845 if (ErrorFound) {
4846 return StmtError();
4847 }
4848 StmtResult SR = S;
4849 unsigned CompletedRegions = 0;
4850 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4851 // Mark all variables in private list clauses as used in inner region.
4852 // Required for proper codegen of combined directives.
4853 // TODO: add processing for other clauses.
4854 if (ThisCaptureRegion != OMPD_unknown) {
4855 for (const clang::OMPClauseWithPreInit *C : PICs) {
4856 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4857 // Find the particular capture region for the clause if the
4858 // directive is a combined one with multiple capture regions.
4859 // If the directive is not a combined one, the capture region
4860 // associated with the clause is OMPD_unknown and is generated
4861 // only once.
4862 if (CaptureRegion == ThisCaptureRegion ||
4863 CaptureRegion == OMPD_unknown) {
4864 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4865 for (Decl *D : DS->decls())
4866 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4867 }
4868 }
4869 }
4870 }
4871 if (ThisCaptureRegion == OMPD_target) {
4872 // Capture allocator traits in the target region. They are used implicitly
4873 // and, thus, are not captured by default.
4874 for (OMPClause *C : Clauses) {
4875 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4876 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4877 ++I) {
4878 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4879 if (Expr *E = D.AllocatorTraits)
4880 MarkDeclarationsReferencedInExpr(E);
4881 }
4882 continue;
4883 }
4884 }
4885 }
4886 if (ThisCaptureRegion == OMPD_parallel) {
4887 // Capture temp arrays for inscan reductions and locals in aligned
4888 // clauses.
4889 for (OMPClause *C : Clauses) {
4890 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4891 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4892 continue;
4893 for (Expr *E : RC->copy_array_temps())
4894 MarkDeclarationsReferencedInExpr(E);
4895 }
4896 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4897 for (Expr *E : AC->varlists())
4898 MarkDeclarationsReferencedInExpr(E);
4899 }
4900 }
4901 }
4902 if (++CompletedRegions == CaptureRegions.size())
4903 DSAStack->setBodyComplete();
4904 SR = ActOnCapturedRegionEnd(SR.get());
4905 }
4906 return SR;
4907}
4908
4909static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4910 OpenMPDirectiveKind CancelRegion,
4911 SourceLocation StartLoc) {
4912 // CancelRegion is only needed for cancel and cancellation_point.
4913 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4914 return false;
4915
4916 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4917 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4918 return false;
4919
4920 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4921 << getOpenMPDirectiveName(CancelRegion);
4922 return true;
4923}
4924
4925static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4926 OpenMPDirectiveKind CurrentRegion,
4927 const DeclarationNameInfo &CurrentName,
4928 OpenMPDirectiveKind CancelRegion,
4929 OpenMPBindClauseKind BindKind,
4930 SourceLocation StartLoc) {
4931 if (Stack->getCurScope()) {
4932 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4933 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4934 bool NestingProhibited = false;
4935 bool CloseNesting = true;
4936 bool OrphanSeen = false;
4937 enum {
4938 NoRecommend,
4939 ShouldBeInParallelRegion,
4940 ShouldBeInOrderedRegion,
4941 ShouldBeInTargetRegion,
4942 ShouldBeInTeamsRegion,
4943 ShouldBeInLoopSimdRegion,
4944 } Recommend = NoRecommend;
4945 if (isOpenMPSimdDirective(ParentRegion) &&
4946 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4947 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4948 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4949 CurrentRegion != OMPD_scan))) {
4950 // OpenMP [2.16, Nesting of Regions]
4951 // OpenMP constructs may not be nested inside a simd region.
4952 // OpenMP [2.8.1,simd Construct, Restrictions]
4953 // An ordered construct with the simd clause is the only OpenMP
4954 // construct that can appear in the simd region.
4955 // Allowing a SIMD construct nested in another SIMD construct is an
4956 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4957 // message.
4958 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4959 // The only OpenMP constructs that can be encountered during execution of
4960 // a simd region are the atomic construct, the loop construct, the simd
4961 // construct and the ordered construct with the simd clause.
4962 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4963 ? diag::err_omp_prohibited_region_simd
4964 : diag::warn_omp_nesting_simd)
4965 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4966 return CurrentRegion != OMPD_simd;
4967 }
4968 if (ParentRegion == OMPD_atomic) {
4969 // OpenMP [2.16, Nesting of Regions]
4970 // OpenMP constructs may not be nested inside an atomic region.
4971 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4972 return true;
4973 }
4974 if (CurrentRegion == OMPD_section) {
4975 // OpenMP [2.7.2, sections Construct, Restrictions]
4976 // Orphaned section directives are prohibited. That is, the section
4977 // directives must appear within the sections construct and must not be
4978 // encountered elsewhere in the sections region.
4979 if (ParentRegion != OMPD_sections &&
4980 ParentRegion != OMPD_parallel_sections) {
4981 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4982 << (ParentRegion != OMPD_unknown)
4983 << getOpenMPDirectiveName(ParentRegion);
4984 return true;
4985 }
4986 return false;
4987 }
4988 // Allow some constructs (except teams and cancellation constructs) to be
4989 // orphaned (they could be used in functions, called from OpenMP regions
4990 // with the required preconditions).
4991 if (ParentRegion == OMPD_unknown &&
4992 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4993 CurrentRegion != OMPD_cancellation_point &&
4994 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4995 return false;
4996 if (CurrentRegion == OMPD_cancellation_point ||
4997 CurrentRegion == OMPD_cancel) {
4998 // OpenMP [2.16, Nesting of Regions]
4999 // A cancellation point construct for which construct-type-clause is
5000 // taskgroup must be nested inside a task construct. A cancellation
5001 // point construct for which construct-type-clause is not taskgroup must
5002 // be closely nested inside an OpenMP construct that matches the type
5003 // specified in construct-type-clause.
5004 // A cancel construct for which construct-type-clause is taskgroup must be
5005 // nested inside a task construct. A cancel construct for which
5006 // construct-type-clause is not taskgroup must be closely nested inside an
5007 // OpenMP construct that matches the type specified in
5008 // construct-type-clause.
5009 NestingProhibited =
5010 !((CancelRegion == OMPD_parallel &&
5011 (ParentRegion == OMPD_parallel ||
5012 ParentRegion == OMPD_target_parallel)) ||
5013 (CancelRegion == OMPD_for &&
5014 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5015 ParentRegion == OMPD_target_parallel_for ||
5016 ParentRegion == OMPD_distribute_parallel_for ||
5017 ParentRegion == OMPD_teams_distribute_parallel_for ||
5018 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5019 (CancelRegion == OMPD_taskgroup &&
5020 (ParentRegion == OMPD_task ||
5021 (SemaRef.getLangOpts().OpenMP >= 50 &&
5022 (ParentRegion == OMPD_taskloop ||
5023 ParentRegion == OMPD_master_taskloop ||
5024 ParentRegion == OMPD_masked_taskloop ||
5025 ParentRegion == OMPD_parallel_masked_taskloop ||
5026 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5027 (CancelRegion == OMPD_sections &&
5028 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5029 ParentRegion == OMPD_parallel_sections)));
5030 OrphanSeen = ParentRegion == OMPD_unknown;
5031 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5032 // OpenMP 5.1 [2.22, Nesting of Regions]
5033 // A masked region may not be closely nested inside a worksharing, loop,
5034 // atomic, task, or taskloop region.
5035 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5036 isOpenMPGenericLoopDirective(ParentRegion) ||
5037 isOpenMPTaskingDirective(ParentRegion);
5038 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5039 // OpenMP [2.16, Nesting of Regions]
5040 // A critical region may not be nested (closely or otherwise) inside a
5041 // critical region with the same name. Note that this restriction is not
5042 // sufficient to prevent deadlock.
5043 SourceLocation PreviousCriticalLoc;
5044 bool DeadLock = Stack->hasDirective(
5045 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5046 const DeclarationNameInfo &DNI,
5047 SourceLocation Loc) {
5048 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5049 PreviousCriticalLoc = Loc;
5050 return true;
5051 }
5052 return false;
5053 },
5054 false /* skip top directive */);
5055 if (DeadLock) {
5056 SemaRef.Diag(StartLoc,
5057 diag::err_omp_prohibited_region_critical_same_name)
5058 << CurrentName.getName();
5059 if (PreviousCriticalLoc.isValid())
5060 SemaRef.Diag(PreviousCriticalLoc,
5061 diag::note_omp_previous_critical_region);
5062 return true;
5063 }
5064 } else if (CurrentRegion == OMPD_barrier) {
5065 // OpenMP 5.1 [2.22, Nesting of Regions]
5066 // A barrier region may not be closely nested inside a worksharing, loop,
5067 // task, taskloop, critical, ordered, atomic, or masked region.
5068 NestingProhibited =
5069 isOpenMPWorksharingDirective(ParentRegion) ||
5070 isOpenMPGenericLoopDirective(ParentRegion) ||
5071 isOpenMPTaskingDirective(ParentRegion) ||
5072 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5073 ParentRegion == OMPD_parallel_master ||
5074 ParentRegion == OMPD_parallel_masked ||
5075 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5076 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5077 !isOpenMPParallelDirective(CurrentRegion) &&
5078 !isOpenMPTeamsDirective(CurrentRegion)) {
5079 // OpenMP 5.1 [2.22, Nesting of Regions]
5080 // A loop region that binds to a parallel region or a worksharing region
5081 // may not be closely nested inside a worksharing, loop, task, taskloop,
5082 // critical, ordered, atomic, or masked region.
5083 NestingProhibited =
5084 isOpenMPWorksharingDirective(ParentRegion) ||
5085 isOpenMPGenericLoopDirective(ParentRegion) ||
5086 isOpenMPTaskingDirective(ParentRegion) ||
5087 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5088 ParentRegion == OMPD_parallel_master ||
5089 ParentRegion == OMPD_parallel_masked ||
5090 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5091 Recommend = ShouldBeInParallelRegion;
5092 } else if (CurrentRegion == OMPD_ordered) {
5093 // OpenMP [2.16, Nesting of Regions]
5094 // An ordered region may not be closely nested inside a critical,
5095 // atomic, or explicit task region.
5096 // An ordered region must be closely nested inside a loop region (or
5097 // parallel loop region) with an ordered clause.
5098 // OpenMP [2.8.1,simd Construct, Restrictions]
5099 // An ordered construct with the simd clause is the only OpenMP construct
5100 // that can appear in the simd region.
5101 NestingProhibited = ParentRegion == OMPD_critical ||
5102 isOpenMPTaskingDirective(ParentRegion) ||
5103 !(isOpenMPSimdDirective(ParentRegion) ||
5104 Stack->isParentOrderedRegion());
5105 Recommend = ShouldBeInOrderedRegion;
5106 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5107 // OpenMP [2.16, Nesting of Regions]
5108 // If specified, a teams construct must be contained within a target
5109 // construct.
5110 NestingProhibited =
5111 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5112 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5113 ParentRegion != OMPD_target);
5114 OrphanSeen = ParentRegion == OMPD_unknown;
5115 Recommend = ShouldBeInTargetRegion;
5116 } else if (CurrentRegion == OMPD_scan) {
5117 // OpenMP [2.16, Nesting of Regions]
5118 // If specified, a teams construct must be contained within a target
5119 // construct.
5120 NestingProhibited =
5121 SemaRef.LangOpts.OpenMP < 50 ||
5122 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5123 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5124 ParentRegion != OMPD_parallel_for_simd);
5125 OrphanSeen = ParentRegion == OMPD_unknown;
5126 Recommend = ShouldBeInLoopSimdRegion;
5127 }
5128 if (!NestingProhibited &&
5129 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5130 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5131 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5132 // OpenMP [5.1, 2.22, Nesting of Regions]
5133 // distribute, distribute simd, distribute parallel worksharing-loop,
5134 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5135 // including any parallel regions arising from combined constructs,
5136 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5137 // only OpenMP regions that may be strictly nested inside the teams
5138 // region.
5139 //
5140 // As an extension, we permit atomic within teams as well.
5141 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5142 !isOpenMPDistributeDirective(CurrentRegion) &&
5143 CurrentRegion != OMPD_loop &&
5144 !(SemaRef.getLangOpts().OpenMPExtensions &&
5145 CurrentRegion == OMPD_atomic);
5146 Recommend = ShouldBeInParallelRegion;
5147 }
5148 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5149 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5150 // If the bind clause is present on the loop construct and binding is
5151 // teams then the corresponding loop region must be strictly nested inside
5152 // a teams region.
5153 NestingProhibited = BindKind == OMPC_BIND_teams &&
5154 ParentRegion != OMPD_teams &&
5155 ParentRegion != OMPD_target_teams;
5156 Recommend = ShouldBeInTeamsRegion;
5157 }
5158 if (!NestingProhibited &&
5159 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5160 // OpenMP 4.5 [2.17 Nesting of Regions]
5161 // The region associated with the distribute construct must be strictly
5162 // nested inside a teams region
5163 NestingProhibited =
5164 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5165 Recommend = ShouldBeInTeamsRegion;
5166 }
5167 if (!NestingProhibited &&
5168 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5169 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5170 // OpenMP 4.5 [2.17 Nesting of Regions]
5171 // If a target, target update, target data, target enter data, or
5172 // target exit data construct is encountered during execution of a
5173 // target region, the behavior is unspecified.
5174 NestingProhibited = Stack->hasDirective(
5175 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5178 OffendingRegion = K;
5179 return true;
5180 }
5181 return false;
5182 },
5183 false /* don't skip top directive */);
5184 CloseNesting = false;
5185 }
5186 if (NestingProhibited) {
5187 if (OrphanSeen) {
5188 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5189 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5190 } else {
5191 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5192 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5193 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5194 }
5195 return true;
5196 }
5197 }
5198 return false;
5199}
5200
5206 ArrayRef<OMPClause *> Clauses,
5207 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5208 bool ErrorFound = false;
5209 unsigned NamedModifiersNumber = 0;
5210 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5211 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5212 SmallVector<SourceLocation, 4> NameModifierLoc;
5213 for (const OMPClause *C : Clauses) {
5214 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5215 // At most one if clause without a directive-name-modifier can appear on
5216 // the directive.
5217 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5218 if (FoundNameModifiers[CurNM]) {
5219 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5220 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5221 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5222 ErrorFound = true;
5223 } else if (CurNM != OMPD_unknown) {
5224 NameModifierLoc.push_back(IC->getNameModifierLoc());
5225 ++NamedModifiersNumber;
5226 }
5227 FoundNameModifiers[CurNM] = IC;
5228 if (CurNM == OMPD_unknown)
5229 continue;
5230 // Check if the specified name modifier is allowed for the current
5231 // directive.
5232 // At most one if clause with the particular directive-name-modifier can
5233 // appear on the directive.
5234 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5235 S.Diag(IC->getNameModifierLoc(),
5236 diag::err_omp_wrong_if_directive_name_modifier)
5237 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5238 ErrorFound = true;
5239 }
5240 }
5241 }
5242 // If any if clause on the directive includes a directive-name-modifier then
5243 // all if clauses on the directive must include a directive-name-modifier.
5244 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5245 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5246 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5247 diag::err_omp_no_more_if_clause);
5248 } else {
5249 std::string Values;
5250 std::string Sep(", ");
5251 unsigned AllowedCnt = 0;
5252 unsigned TotalAllowedNum =
5253 AllowedNameModifiers.size() - NamedModifiersNumber;
5254 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5255 ++Cnt) {
5256 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5257 if (!FoundNameModifiers[NM]) {
5258 Values += "'";
5259 Values += getOpenMPDirectiveName(NM);
5260 Values += "'";
5261 if (AllowedCnt + 2 == TotalAllowedNum)
5262 Values += " or ";
5263 else if (AllowedCnt + 1 != TotalAllowedNum)
5264 Values += Sep;
5265 ++AllowedCnt;
5266 }
5267 }
5268 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5269 diag::err_omp_unnamed_if_clause)
5270 << (TotalAllowedNum > 1) << Values;
5271 }
5272 for (SourceLocation Loc : NameModifierLoc) {
5273 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5274 }
5275 ErrorFound = true;
5276 }
5277 return ErrorFound;
5278}
5279
5280static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5281 SourceLocation &ELoc,
5282 SourceRange &ERange,
5283 bool AllowArraySection) {
5284 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5286 return std::make_pair(nullptr, true);
5287
5288 // OpenMP [3.1, C/C++]
5289 // A list item is a variable name.
5290 // OpenMP [2.9.3.3, Restrictions, p.1]
5291 // A variable that is part of another variable (as an array or
5292 // structure element) cannot appear in a private clause.
5293 RefExpr = RefExpr->IgnoreParens();
5294 enum {
5295 NoArrayExpr = -1,
5296 ArraySubscript = 0,
5297 OMPArraySection = 1
5298 } IsArrayExpr = NoArrayExpr;
5299 if (AllowArraySection) {
5300 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5301 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5302 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5303 Base = TempASE->getBase()->IgnoreParenImpCasts();
5304 RefExpr = Base;
5305 IsArrayExpr = ArraySubscript;
5306 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5307 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5308 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5309 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5310 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5311 Base = TempASE->getBase()->IgnoreParenImpCasts();
5312 RefExpr = Base;
5313 IsArrayExpr = OMPArraySection;
5314 }
5315 }
5316 ELoc = RefExpr->getExprLoc();
5317 ERange = RefExpr->getSourceRange();
5318 RefExpr = RefExpr->IgnoreParenImpCasts();
5319 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5320 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5321 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5322 (S.getCurrentThisType().isNull() || !ME ||
5323 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5324 !isa<FieldDecl>(ME->getMemberDecl()))) {
5325 if (IsArrayExpr != NoArrayExpr) {
5326 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5327 << IsArrayExpr << ERange;
5328 } else {
5329 S.Diag(ELoc,
5330 AllowArraySection
5331 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5332 : diag::err_omp_expected_var_name_member_expr)
5333 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5334 }
5335 return std::make_pair(nullptr, false);
5336 }
5337 return std::make_pair(
5338 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5339}
5340
5341namespace {
5342/// Checks if the allocator is used in uses_allocators clause to be allowed in
5343/// target regions.
5344class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5345 DSAStackTy *S = nullptr;
5346
5347public:
5348 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5349 return S->isUsesAllocatorsDecl(E->getDecl())
5350 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5351 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5352 }
5353 bool VisitStmt(const Stmt *S) {
5354 for (const Stmt *Child : S->children()) {
5355 if (Child && Visit(Child))
5356 return true;
5357 }
5358 return false;
5359 }
5360 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5361};
5362} // namespace
5363
5364static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5365 ArrayRef<OMPClause *> Clauses) {
5366 assert(!S.CurContext->isDependentContext() &&
5367 "Expected non-dependent context.");
5368 auto AllocateRange =
5369 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5370 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5371 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5372 return isOpenMPPrivate(C->getClauseKind());
5373 });
5374 for (OMPClause *Cl : PrivateRange) {
5376 if (Cl->getClauseKind() == OMPC_private) {
5377 auto *PC = cast<OMPPrivateClause>(Cl);
5378 I = PC->private_copies().begin();
5379 It = PC->varlist_begin();
5380 Et = PC->varlist_end();
5381 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5382 auto *PC = cast<OMPFirstprivateClause>(Cl);
5383 I = PC->private_copies().begin();
5384 It = PC->varlist_begin();
5385 Et = PC->varlist_end();
5386 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5387 auto *PC = cast<OMPLastprivateClause>(Cl);
5388 I = PC->private_copies().begin();
5389 It = PC->varlist_begin();
5390 Et = PC->varlist_end();
5391 } else if (Cl->getClauseKind() == OMPC_linear) {
5392 auto *PC = cast<OMPLinearClause>(Cl);
5393 I = PC->privates().begin();
5394 It = PC->varlist_begin();
5395 Et = PC->varlist_end();
5396 } else if (Cl->getClauseKind() == OMPC_reduction) {
5397 auto *PC = cast<OMPReductionClause>(Cl);
5398 I = PC->privates().begin();
5399 It = PC->varlist_begin();
5400 Et = PC->varlist_end();
5401 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5402 auto *PC = cast<OMPTaskReductionClause>(Cl);
5403 I = PC->privates().begin();
5404 It = PC->varlist_begin();
5405 Et = PC->varlist_end();
5406 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5407 auto *PC = cast<OMPInReductionClause>(Cl);
5408 I = PC->privates().begin();
5409 It = PC->varlist_begin();
5410 Et = PC->varlist_end();
5411 } else {
5412 llvm_unreachable("Expected private clause.");
5413 }
5414 for (Expr *E : llvm::make_range(It, Et)) {
5415 if (!*I) {
5416 ++I;
5417 continue;
5418 }
5419 SourceLocation ELoc;
5420 SourceRange ERange;
5421 Expr *SimpleRefExpr = E;
5422 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5423 /*AllowArraySection=*/true);
5424 DeclToCopy.try_emplace(Res.first,
5425 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5426 ++I;
5427 }
5428 }
5429 for (OMPClause *C : AllocateRange) {
5430 auto *AC = cast<OMPAllocateClause>(C);
5431 if (S.getLangOpts().OpenMP >= 50 &&
5432 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5433 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5434 AC->getAllocator()) {
5435 Expr *Allocator = AC->getAllocator();
5436 // OpenMP, 2.12.5 target Construct
5437 // Memory allocators that do not appear in a uses_allocators clause cannot
5438 // appear as an allocator in an allocate clause or be used in the target
5439 // region unless a requires directive with the dynamic_allocators clause
5440 // is present in the same compilation unit.
5441 AllocatorChecker Checker(Stack);
5442 if (Checker.Visit(Allocator))
5443 S.Diag(Allocator->getExprLoc(),
5444 diag::err_omp_allocator_not_in_uses_allocators)
5445 << Allocator->getSourceRange();
5446 }
5447 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5448 getAllocatorKind(S, Stack, AC->getAllocator());
5449 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5450 // For task, taskloop or target directives, allocation requests to memory
5451 // allocators with the trait access set to thread result in unspecified
5452 // behavior.
5453 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5454 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5455 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5456 S.Diag(AC->getAllocator()->getExprLoc(),
5457 diag::warn_omp_allocate_thread_on_task_target_directive)
5458 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5459 }
5460 for (Expr *E : AC->varlists()) {
5461 SourceLocation ELoc;
5462 SourceRange ERange;
5463 Expr *SimpleRefExpr = E;
5464 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5465 ValueDecl *VD = Res.first;
5466 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5467 if (!isOpenMPPrivate(Data.CKind)) {
5468 S.Diag(E->getExprLoc(),
5469 diag::err_omp_expected_private_copy_for_allocate);
5470 continue;
5471 }
5472 VarDecl *PrivateVD = DeclToCopy[VD];
5473 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5474 AllocatorKind, AC->getAllocator()))
5475 continue;
5476 // Placeholder until allocate clause supports align modifier.
5477 Expr *Alignment = nullptr;
5478 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5479 Alignment, E->getSourceRange());
5480 }
5481 }
5482}
5483
5484namespace {
5485/// Rewrite statements and expressions for Sema \p Actions CurContext.
5486///
5487/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5488/// context. DeclRefExpr used inside the new context are changed to refer to the
5489/// captured variable instead.
5490class CaptureVars : public TreeTransform<CaptureVars> {
5491 using BaseTransform = TreeTransform<CaptureVars>;
5492
5493public:
5494 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5495
5496 bool AlwaysRebuild() { return true; }
5497};
5498} // namespace
5499
5500static VarDecl *precomputeExpr(Sema &Actions,
5501 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5502 StringRef Name) {
5503 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5504 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5505 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5506 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5507 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5508 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5509 BodyStmts.push_back(NewDeclStmt);
5510 return NewVar;
5511}
5512
5513/// Create a closure that computes the number of iterations of a loop.
5514///
5515/// \param Actions The Sema object.
5516/// \param LogicalTy Type for the logical iteration number.
5517/// \param Rel Comparison operator of the loop condition.
5518/// \param StartExpr Value of the loop counter at the first iteration.
5519/// \param StopExpr Expression the loop counter is compared against in the loop
5520/// condition. \param StepExpr Amount of increment after each iteration.
5521///
5522/// \return Closure (CapturedStmt) of the distance calculation.
5523static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5525 Expr *StartExpr, Expr *StopExpr,
5526 Expr *StepExpr) {
5527 ASTContext &Ctx = Actions.getASTContext();
5528 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5529
5530 // Captured regions currently don't support return values, we use an
5531 // out-parameter instead. All inputs are implicit captures.
5532 // TODO: Instead of capturing each DeclRefExpr occurring in
5533 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5534 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5535 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5536 {StringRef(), QualType()}};
5537 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5538
5539 Stmt *Body;
5540 {
5541 Sema::CompoundScopeRAII CompoundScope(Actions);
5543
5544 // Get the LValue expression for the result.
5545 ImplicitParamDecl *DistParam = CS->getParam(0);
5546 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5547 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5548
5549 SmallVector<Stmt *, 4> BodyStmts;
5550
5551 // Capture all referenced variable references.
5552 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5553 // CapturedStmt, we could compute them before and capture the result, to be
5554 // used jointly with the LoopVar function.
5555 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5556 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5557 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5558 auto BuildVarRef = [&](VarDecl *VD) {
5559 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5560 };
5561
5563 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5565 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5566 Expr *Dist;
5567 if (Rel == BO_NE) {
5568 // When using a != comparison, the increment can be +1 or -1. This can be
5569 // dynamic at runtime, so we need to check for the direction.
5570 Expr *IsNegStep = AssertSuccess(
5571 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5572
5573 // Positive increment.
5574 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5575 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5576 ForwardRange = AssertSuccess(
5577 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5578 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5579 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5580
5581 // Negative increment.
5582 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5583 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5584 BackwardRange = AssertSuccess(
5585 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5586 Expr *NegIncAmount = AssertSuccess(
5587 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5588 Expr *BackwardDist = AssertSuccess(
5589 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5590
5591 // Use the appropriate case.
5592 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5593 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5594 } else {
5595 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5596 "Expected one of these relational operators");
5597
5598 // We can derive the direction from any other comparison operator. It is
5599 // non well-formed OpenMP if Step increments/decrements in the other
5600 // directions. Whether at least the first iteration passes the loop
5601 // condition.
5602 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5603 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5604
5605 // Compute the range between first and last counter value.
5606 Expr *Range;
5607 if (Rel == BO_GE || Rel == BO_GT)
5608 Range = AssertSuccess(Actions.BuildBinOp(
5609 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5610 else
5611 Range = AssertSuccess(Actions.BuildBinOp(
5612 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5613
5614 // Ensure unsigned range space.
5615 Range =
5616 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5617
5618 if (Rel == BO_LE || Rel == BO_GE) {
5619 // Add one to the range if the relational operator is inclusive.
5620 Range =
5621 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5622 }
5623
5624 // Divide by the absolute step amount. If the range is not a multiple of
5625 // the step size, rounding-up the effective upper bound ensures that the
5626 // last iteration is included.
5627 // Note that the rounding-up may cause an overflow in a temporry that
5628 // could be avoided, but would have occurred in a C-style for-loop as well.
5629 Expr *Divisor = BuildVarRef(NewStep);
5630 if (Rel == BO_GE || Rel == BO_GT)
5631 Divisor =
5632 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5633 Expr *DivisorMinusOne =
5634 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5635 Expr *RangeRoundUp = AssertSuccess(
5636 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5637 Dist = AssertSuccess(
5638 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5639
5640 // If there is not at least one iteration, the range contains garbage. Fix
5641 // to zero in this case.
5642 Dist = AssertSuccess(
5643 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5644 }
5645
5646 // Assign the result to the out-parameter.
5647 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5648 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5649 BodyStmts.push_back(ResultAssign);
5650
5651 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5652 }
5653
5654 return cast<CapturedStmt>(
5655 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5656}
5657
5658/// Create a closure that computes the loop variable from the logical iteration
5659/// number.
5660///
5661/// \param Actions The Sema object.
5662/// \param LoopVarTy Type for the loop variable used for result value.
5663/// \param LogicalTy Type for the logical iteration number.
5664/// \param StartExpr Value of the loop counter at the first iteration.
5665/// \param Step Amount of increment after each iteration.
5666/// \param Deref Whether the loop variable is a dereference of the loop
5667/// counter variable.
5668///
5669/// \return Closure (CapturedStmt) of the loop value calculation.
5670static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5671 QualType LogicalTy,
5672 DeclRefExpr *StartExpr, Expr *Step,
5673 bool Deref) {
5674 ASTContext &Ctx = Actions.getASTContext();
5675
5676 // Pass the result as an out-parameter. Passing as return value would require
5677 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5678 // invoke a copy constructor.
5679 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5680 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5681 {"Logical", LogicalTy},
5682 {StringRef(), QualType()}};
5683 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5684
5685 // Capture the initial iterator which represents the LoopVar value at the
5686 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5687 // it in every iteration, capture it by value before it is modified.
5688 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5689 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5691 (void)Invalid;
5692 assert(!Invalid && "Expecting capture-by-value to work.");
5693
5694 Expr *Body;
5695 {
5696 Sema::CompoundScopeRAII CompoundScope(Actions);
5697 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5698
5699 ImplicitParamDecl *TargetParam = CS->getParam(0);
5700 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5701 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5702 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5703 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5704 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5705
5706 // Capture the Start expression.
5707 CaptureVars Recap(Actions);
5708 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5709 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5710
5711 Expr *Skip = AssertSuccess(
5712 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5713 // TODO: Explicitly cast to the iterator's difference_type instead of
5714 // relying on implicit conversion.
5715 Expr *Advanced =
5716 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5717
5718 if (Deref) {
5719 // For range-based for-loops convert the loop counter value to a concrete
5720 // loop variable value by dereferencing the iterator.
5721 Advanced =
5722 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5723 }
5724
5725 // Assign the result to the output parameter.
5726 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5727 BO_Assign, TargetRef, Advanced));
5728 }
5729 return cast<CapturedStmt>(
5730 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5731}
5732
5734 ASTContext &Ctx = getASTContext();
5735
5736 // Extract the common elements of ForStmt and CXXForRangeStmt:
5737 // Loop variable, repeat condition, increment
5738 Expr *Cond, *Inc;
5739 VarDecl *LIVDecl, *LUVDecl;
5740 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5741 Stmt *Init = For->getInit();
5742 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5743 // For statement declares loop variable.
5744 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5745 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5746 // For statement reuses variable.
5747 assert(LCAssign->getOpcode() == BO_Assign &&
5748 "init part must be a loop variable assignment");
5749 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5750 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5751 } else
5752 llvm_unreachable("Cannot determine loop variable");
5753 LUVDecl = LIVDecl;
5754
5755 Cond = For->getCond();
5756 Inc = For->getInc();
5757 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5758 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5759 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5760 LUVDecl = RangeFor->getLoopVariable();
5761
5762 Cond = RangeFor->getCond();
5763 Inc = RangeFor->getInc();
5764 } else
5765 llvm_unreachable("unhandled kind of loop");
5766
5767 QualType CounterTy = LIVDecl->getType();
5768 QualType LVTy = LUVDecl->getType();
5769
5770 // Analyze the loop condition.
5771 Expr *LHS, *RHS;
5772 BinaryOperator::Opcode CondRel;
5774 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5775 LHS = CondBinExpr->getLHS();
5776 RHS = CondBinExpr->getRHS();
5777 CondRel = CondBinExpr->getOpcode();
5778 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5779 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5780 LHS = CondCXXOp->getArg(0);
5781 RHS = CondCXXOp->getArg(1);
5782 switch (CondCXXOp->getOperator()) {
5783 case OO_ExclaimEqual:
5784 CondRel = BO_NE;
5785 break;
5786 case OO_Less:
5787 CondRel = BO_LT;
5788 break;
5789 case OO_LessEqual:
5790 CondRel = BO_LE;
5791 break;
5792 case OO_Greater:
5793 CondRel = BO_GT;
5794 break;
5795 case OO_GreaterEqual:
5796 CondRel = BO_GE;
5797 break;
5798 default:
5799 llvm_unreachable("unexpected iterator operator");
5800 }
5801 } else
5802 llvm_unreachable("unexpected loop condition");
5803
5804 // Normalize such that the loop counter is on the LHS.
5805 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5806 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5807 std::swap(LHS, RHS);
5808 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5809 }
5810 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5811
5812 // Decide the bit width for the logical iteration counter. By default use the
5813 // unsigned ptrdiff_t integer size (for iterators and pointers).
5814 // TODO: For iterators, use iterator::difference_type,
5815 // std::iterator_traits<>::difference_type or decltype(it - end).
5816 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5817 if (CounterTy->isIntegerType()) {
5818 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5819 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5820 }
5821
5822 // Analyze the loop increment.
5823 Expr *Step;
5824 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5825 int Direction;
5826 switch (IncUn->getOpcode()) {
5827 case UO_PreInc:
5828 case UO_PostInc:
5829 Direction = 1;
5830 break;
5831 case UO_PreDec:
5832 case UO_PostDec:
5833 Direction = -1;
5834 break;
5835 default:
5836 llvm_unreachable("unhandled unary increment operator");
5837 }
5839 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5840 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5841 if (IncBin->getOpcode() == BO_AddAssign) {
5842 Step = IncBin->getRHS();
5843 } else if (IncBin->getOpcode() == BO_SubAssign) {
5844 Step =
5845 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5846 } else
5847 llvm_unreachable("unhandled binary increment operator");
5848 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5849 switch (CondCXXOp->getOperator()) {
5850 case OO_PlusPlus:
5852 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5853 break;
5854 case OO_MinusMinus:
5856 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5857 break;
5858 case OO_PlusEqual:
5859 Step = CondCXXOp->getArg(1);
5860 break;
5861 case OO_MinusEqual:
5862 Step = AssertSuccess(
5863 BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5864 break;
5865 default:
5866 llvm_unreachable("unhandled overloaded increment operator");
5867 }
5868 } else
5869 llvm_unreachable("unknown increment expression");
5870
5871 CapturedStmt *DistanceFunc =
5872 buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
5873 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5874 *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5875 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5876 {}, nullptr, nullptr, {}, nullptr);
5877 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5878 LoopVarFunc, LVRef);
5879}
5880
5882 // Handle a literal loop.
5883 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5884 return ActOnOpenMPCanonicalLoop(AStmt);
5885
5886 // If not a literal loop, it must be the result of a loop transformation.
5888 assert(
5889 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5890 "Loop transformation directive expected");
5891 return LoopTransform;
5892}
5893
5895 CXXScopeSpec &MapperIdScopeSpec,
5896 const DeclarationNameInfo &MapperId,
5897 QualType Type,
5898 Expr *UnresolvedMapper);
5899
5900/// Perform DFS through the structure/class data members trying to find
5901/// member(s) with user-defined 'default' mapper and generate implicit map
5902/// clauses for such members with the found 'default' mapper.
5903static void
5906 // Check for the deault mapper for data members.
5907 if (S.getLangOpts().OpenMP < 50)
5908 return;
5909 SmallVector<OMPClause *, 4> ImplicitMaps;
5910 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5911 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5912 if (!C)
5913 continue;
5914 SmallVector<Expr *, 4> SubExprs;
5915 auto *MI = C->mapperlist_begin();
5916 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5917 ++I, ++MI) {
5918 // Expression is mapped using mapper - skip it.
5919 if (*MI)
5920 continue;
5921 Expr *E = *I;
5922 // Expression is dependent - skip it, build the mapper when it gets
5923 // instantiated.
5924 if (E->isTypeDependent() || E->isValueDependent() ||
5926 continue;
5927 // Array section - need to check for the mapping of the array section
5928 // element.
5929 QualType CanonType = E->getType().getCanonicalType();
5930 if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
5931 const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
5932 QualType BaseType =
5934 QualType ElemType;
5935 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5936 ElemType = ATy->getElementType();
5937 else
5938 ElemType = BaseType->getPointeeType();
5939 CanonType = ElemType;
5940 }
5941
5942 // DFS over data members in structures/classes.
5944 1, {CanonType, nullptr});
5945 llvm::DenseMap<const Type *, Expr *> Visited;
5947 1, {nullptr, 1});
5948 while (!Types.empty()) {
5949 QualType BaseType;
5950 FieldDecl *CurFD;
5951 std::tie(BaseType, CurFD) = Types.pop_back_val();
5952 while (ParentChain.back().second == 0)
5953 ParentChain.pop_back();
5954 --ParentChain.back().second;
5955 if (BaseType.isNull())
5956 continue;
5957 // Only structs/classes are allowed to have mappers.
5958 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5959 if (!RD)
5960 continue;
5961 auto It = Visited.find(BaseType.getTypePtr());
5962 if (It == Visited.end()) {
5963 // Try to find the associated user-defined mapper.
5964 CXXScopeSpec MapperIdScopeSpec;
5965 DeclarationNameInfo DefaultMapperId;
5967 &S.Context.Idents.get("default")));
5968 DefaultMapperId.setLoc(E->getExprLoc());
5970 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5971 BaseType, /*UnresolvedMapper=*/nullptr);
5972 if (ER.isInvalid())
5973 continue;
5974 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5975 }
5976 // Found default mapper.
5977 if (It->second) {
5978 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5980 OE->setIsUnique(/*V=*/true);
5981 Expr *BaseExpr = OE;
5982 for (const auto &P : ParentChain) {
5983 if (P.first) {
5984 BaseExpr = S.BuildMemberExpr(
5985 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5987 DeclAccessPair::make(P.first, P.first->getAccess()),
5988 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5989 P.first->getType(), VK_LValue, OK_Ordinary);
5990 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5991 }
5992 }
5993 if (CurFD)
5994 BaseExpr = S.BuildMemberExpr(
5995 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5997 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5998 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5999 CurFD->getType(), VK_LValue, OK_Ordinary);
6000 SubExprs.push_back(BaseExpr);
6001 continue;
6002 }
6003 // Check for the "default" mapper for data members.
6004 bool FirstIter = true;
6005 for (FieldDecl *FD : RD->fields()) {
6006 if (!FD)
6007 continue;
6008 QualType FieldTy = FD->getType();
6009 if (FieldTy.isNull() ||
6010 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6011 continue;
6012 if (FirstIter) {
6013 FirstIter = false;
6014 ParentChain.emplace_back(CurFD, 1);
6015 } else {
6016 ++ParentChain.back().second;
6017 }
6018 Types.emplace_back(FieldTy, FD);
6019 }
6020 }
6021 }
6022 if (SubExprs.empty())
6023 continue;
6024 CXXScopeSpec MapperIdScopeSpec;
6025 DeclarationNameInfo MapperId;
6026 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6027 C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6028 MapperIdScopeSpec, MapperId, C->getMapType(),
6029 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6030 SubExprs, OMPVarListLocTy()))
6031 Clauses.push_back(NewClause);
6032 }
6033}
6034
6036 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6037 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6038 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6039 StmtResult Res = StmtError();
6041 if (const OMPBindClause *BC =
6042 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6043 BindKind = BC->getBindKind();
6044 // First check CancelRegion which is then used in checkNestingOfRegions.
6045 if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
6046 checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
6047 BindKind, StartLoc))
6048 return StmtError();
6049
6050 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6051 VarsWithInheritedDSAType VarsWithInheritedDSA;
6052 bool ErrorFound = false;
6053 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6054 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6055 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6056 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6057 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6058
6059 // Check default data sharing attributes for referenced variables.
6060 DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
6061 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6062 Stmt *S = AStmt;
6063 while (--ThisCaptureLevel >= 0)
6064 S = cast<CapturedStmt>(S)->getCapturedStmt();
6065 DSAChecker.Visit(S);
6067 !isOpenMPTaskingDirective(Kind)) {
6068 // Visit subcaptures to generate implicit clauses for captured vars.
6069 auto *CS = cast<CapturedStmt>(AStmt);
6071 getOpenMPCaptureRegions(CaptureRegions, Kind);
6072 // Ignore outer tasking regions for target directives.
6073 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6075 DSAChecker.visitSubCaptures(CS);
6076 }
6077 if (DSAChecker.isErrorFound())
6078 return StmtError();
6079 // Generate list of implicitly defined firstprivate variables.
6080 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6081
6082 SmallVector<Expr *, 4> ImplicitFirstprivates(
6083 DSAChecker.getImplicitFirstprivate().begin(),
6084 DSAChecker.getImplicitFirstprivate().end());
6085 SmallVector<Expr *, 4> ImplicitPrivates(
6086 DSAChecker.getImplicitPrivate().begin(),
6087 DSAChecker.getImplicitPrivate().end());
6088 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
6089 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6091 ImplicitMapModifiers[DefaultmapKindNum];
6093 ImplicitMapModifiersLoc[DefaultmapKindNum];
6094 // Get the original location of present modifier from Defaultmap clause.
6095 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6096 for (OMPClause *C : Clauses) {
6097 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6098 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6099 PresentModifierLocs[DMC->getDefaultmapKind()] =
6100 DMC->getDefaultmapModifierLoc();
6101 }
6102 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6103 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6104 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6105 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6106 Kind, static_cast<OpenMPMapClauseKind>(I));
6107 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6108 }
6109 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6110 DSAChecker.getImplicitMapModifier(Kind);
6111 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6112 ImplicitModifier.end());
6113 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6114 ImplicitModifier.size(), PresentModifierLocs[VC]);
6115 }
6116 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6117 for (OMPClause *C : Clauses) {
6118 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6119 for (Expr *E : IRC->taskgroup_descriptors())
6120 if (E)
6121 ImplicitFirstprivates.emplace_back(E);
6122 }
6123 // OpenMP 5.0, 2.10.1 task Construct
6124 // [detach clause]... The event-handle will be considered as if it was
6125 // specified on a firstprivate clause.
6126 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6127 ImplicitFirstprivates.push_back(DC->getEventHandler());
6128 }
6129 if (!ImplicitFirstprivates.empty()) {
6130 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6131 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6132 SourceLocation())) {
6133 ClausesWithImplicit.push_back(Implicit);
6134 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6135 ImplicitFirstprivates.size();
6136 } else {
6137 ErrorFound = true;
6138 }
6139 }
6140 if (!ImplicitPrivates.empty()) {
6141 if (OMPClause *Implicit =
6142 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6144 ClausesWithImplicit.push_back(Implicit);
6145 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6146 ImplicitPrivates.size();
6147 } else {
6148 ErrorFound = true;
6149 }
6150 }
6151 // OpenMP 5.0 [2.19.7]
6152 // If a list item appears in a reduction, lastprivate or linear
6153 // clause on a combined target construct then it is treated as
6154 // if it also appears in a map clause with a map-type of tofrom
6155 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6157 SmallVector<Expr *, 4> ImplicitExprs;
6158 for (OMPClause *C : Clauses) {
6159 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6160 for (Expr *E : RC->varlists())
6161 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6162 ImplicitExprs.emplace_back(E);
6163 }
6164 if (!ImplicitExprs.empty()) {
6165 ArrayRef<Expr *> Exprs = ImplicitExprs;
6166 CXXScopeSpec MapperIdScopeSpec;
6167 DeclarationNameInfo MapperId;
6168 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6169 OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
6170 MapperId, OMPC_MAP_tofrom,
6171 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6172 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6173 ClausesWithImplicit.emplace_back(Implicit);
6174 }
6175 }
6176 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6177 int ClauseKindCnt = -1;
6178 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6179 ++ClauseKindCnt;
6180 if (ImplicitMap.empty())
6181 continue;
6182 CXXScopeSpec MapperIdScopeSpec;
6183 DeclarationNameInfo MapperId;
6184 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6185 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6186 ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6187 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6188 SourceLocation(), SourceLocation(), ImplicitMap,
6189 OMPVarListLocTy())) {
6190 ClausesWithImplicit.emplace_back(Implicit);
6191 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6192 ImplicitMap.size();
6193 } else {
6194 ErrorFound = true;
6195 }
6196 }
6197 }
6198 // Build expressions for implicit maps of data members with 'default'
6199 // mappers.
6200 if (LangOpts.OpenMP >= 50)
6202 ClausesWithImplicit);
6203 }
6204
6205 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6206 switch (Kind) {
6207 case OMPD_parallel:
6208 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6209 EndLoc);
6210 AllowedNameModifiers.push_back(OMPD_parallel);
6211 break;
6212 case OMPD_simd:
6213 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6214 VarsWithInheritedDSA);
6215 if (LangOpts.OpenMP >= 50)
6216 AllowedNameModifiers.push_back(OMPD_simd);
6217 break;
6218 case OMPD_tile:
6219 Res =
6220 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6221 break;
6222 case OMPD_unroll:
6223 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6224 EndLoc);
6225 break;
6226 case OMPD_for:
6227 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6228 VarsWithInheritedDSA);
6229 break;
6230 case OMPD_for_simd:
6231 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6232 EndLoc, VarsWithInheritedDSA);
6233 if (LangOpts.OpenMP >= 50)
6234 AllowedNameModifiers.push_back(OMPD_simd);
6235 break;
6236 case OMPD_sections:
6237 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6238 EndLoc);
6239 break;
6240 case OMPD_section:
6241 assert(ClausesWithImplicit.empty() &&
6242 "No clauses are allowed for 'omp section' directive");
6243 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6244 break;
6245 case OMPD_single:
6246 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6247 EndLoc);
6248 break;
6249 case OMPD_master:
6250 assert(ClausesWithImplicit.empty() &&
6251 "No clauses are allowed for 'omp master' directive");
6252 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6253 break;
6254 case OMPD_masked:
6255 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6256 EndLoc);
6257 break;
6258 case OMPD_critical:
6259 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6260 StartLoc, EndLoc);
6261 break;
6262 case OMPD_parallel_for:
6263 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6264 EndLoc, VarsWithInheritedDSA);
6265 AllowedNameModifiers.push_back(OMPD_parallel);
6266 break;
6267 case OMPD_parallel_for_simd:
6268 Res = ActOnOpenMPParallelForSimdDirective(
6269 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6270 AllowedNameModifiers.push_back(OMPD_parallel);
6271 if (LangOpts.OpenMP >= 50)
6272 AllowedNameModifiers.push_back(OMPD_simd);
6273 break;
6274 case OMPD_parallel_master:
6275 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6276 StartLoc, EndLoc);
6277 AllowedNameModifiers.push_back(OMPD_parallel);
6278 break;
6279 case OMPD_parallel_masked:
6280 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6281 StartLoc, EndLoc);
6282 AllowedNameModifiers.push_back(OMPD_parallel);
6283 break;
6284 case OMPD_parallel_sections:
6285 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6286 StartLoc, EndLoc);
6287 AllowedNameModifiers.push_back(OMPD_parallel);
6288 break;
6289 case OMPD_task:
6290 Res =
6291 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6292 AllowedNameModifiers.push_back(OMPD_task);
6293 break;
6294 case OMPD_taskyield:
6295 assert(ClausesWithImplicit.empty() &&
6296 "No clauses are allowed for 'omp taskyield' directive");
6297 assert(AStmt == nullptr &&
6298 "No associated statement allowed for 'omp taskyield' directive");
6299 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6300 break;
6301 case OMPD_barrier:
6302 assert(ClausesWithImplicit.empty() &&
6303 "No clauses are allowed for 'omp barrier' directive");
6304 assert(AStmt == nullptr &&
6305 "No associated statement allowed for 'omp barrier' directive");
6306 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6307 break;
6308 case OMPD_taskwait:
6309 assert(AStmt == nullptr &&
6310 "No associated statement allowed for 'omp taskwait' directive");
6311 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6312 break;
6313 case OMPD_taskgroup:
6314 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6315 EndLoc);
6316 break;
6317 case OMPD_flush:
6318 assert(AStmt == nullptr &&
6319 "No associated statement allowed for 'omp flush' directive");
6320 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6321 break;
6322 case OMPD_depobj:
6323 assert(AStmt == nullptr &&
6324 "No associated statement allowed for 'omp depobj' directive");
6325 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6326 break;
6327 case OMPD_scan:
6328 assert(AStmt == nullptr &&
6329 "No associated statement allowed for 'omp scan' directive");
6330 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6331 break;
6332 case OMPD_ordered:
6333 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6334 EndLoc);
6335 break;
6336 case OMPD_atomic:
6337 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6338 EndLoc);
6339 break;
6340 case OMPD_teams:
6341 Res =
6342 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6343 break;
6344 case OMPD_target:
6345 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6346 EndLoc);
6347 AllowedNameModifiers.push_back(OMPD_target);
6348 break;
6349 case OMPD_target_parallel:
6350 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6351 StartLoc, EndLoc);
6352 AllowedNameModifiers.push_back(OMPD_target);
6353 AllowedNameModifiers.push_back(OMPD_parallel);
6354 break;
6355 case OMPD_target_parallel_for:
6356 Res = ActOnOpenMPTargetParallelForDirective(
6357 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6358 AllowedNameModifiers.push_back(OMPD_target);
6359 AllowedNameModifiers.push_back(OMPD_parallel);
6360 break;
6361 case OMPD_cancellation_point:
6362 assert(ClausesWithImplicit.empty() &&
6363 "No clauses are allowed for 'omp cancellation point' directive");
6364 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6365 "cancellation point' directive");
6366 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6367 break;
6368 case OMPD_cancel:
6369 assert(AStmt == nullptr &&
6370 "No associated statement allowed for 'omp cancel' directive");
6371 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6372 CancelRegion);
6373 AllowedNameModifiers.push_back(OMPD_cancel);
6374 break;
6375 case OMPD_target_data:
6376 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6377 EndLoc);
6378 AllowedNameModifiers.push_back(OMPD_target_data);
6379 break;
6380 case OMPD_target_enter_data:
6381 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6382 EndLoc, AStmt);
6383 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6384 break;
6385 case OMPD_target_exit_data:
6386 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6387 EndLoc, AStmt);
6388 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6389 break;
6390 case OMPD_taskloop:
6391 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6392 EndLoc, VarsWithInheritedDSA);
6393 AllowedNameModifiers.push_back(OMPD_taskloop);
6394 break;
6395 case OMPD_taskloop_simd:
6396 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6397 EndLoc, VarsWithInheritedDSA);
6398 AllowedNameModifiers.push_back(OMPD_taskloop);
6399 if (LangOpts.OpenMP >= 50)
6400 AllowedNameModifiers.push_back(OMPD_simd);
6401 break;
6402 case OMPD_master_taskloop:
6403 Res = ActOnOpenMPMasterTaskLoopDirective(
6404 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6405 AllowedNameModifiers.push_back(OMPD_taskloop);
6406 break;
6407 case OMPD_masked_taskloop:
6408 Res = ActOnOpenMPMaskedTaskLoopDirective(
6409 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6410 AllowedNameModifiers.push_back(OMPD_taskloop);
6411 break;
6412 case OMPD_master_taskloop_simd:
6413 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6414 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6415 AllowedNameModifiers.push_back(OMPD_taskloop);
6416 if (LangOpts.OpenMP >= 50)
6417 AllowedNameModifiers.push_back(OMPD_simd);
6418 break;
6419 case OMPD_masked_taskloop_simd:
6420 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6421 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6422 if (LangOpts.OpenMP >= 51) {
6423 AllowedNameModifiers.push_back(OMPD_taskloop);
6424 AllowedNameModifiers.push_back(OMPD_simd);
6425 }
6426 break;
6427 case OMPD_parallel_master_taskloop:
6428 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6429 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6430 AllowedNameModifiers.push_back(OMPD_taskloop);
6431 AllowedNameModifiers.push_back(OMPD_parallel);
6432 break;
6433 case OMPD_parallel_masked_taskloop:
6434 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6436 if (LangOpts.OpenMP >= 51) {
6437 AllowedNameModifiers.push_back(OMPD_taskloop);
6438 AllowedNameModifiers.push_back(OMPD_parallel);
6439 }
6440 break;
6441 case OMPD_parallel_master_taskloop_simd:
6442 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6443 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6444 AllowedNameModifiers.push_back(OMPD_taskloop);
6445 AllowedNameModifiers.push_back(OMPD_parallel);
6446 if (LangOpts.OpenMP >= 50)
6447 AllowedNameModifiers.push_back(OMPD_simd);
6448 break;
6449 case OMPD_parallel_masked_taskloop_simd:
6450 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6451 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6452 if (LangOpts.OpenMP >= 51) {
6453 AllowedNameModifiers.push_back(OMPD_taskloop);
6454 AllowedNameModifiers.push_back(OMPD_parallel);
6455 AllowedNameModifiers.push_back(OMPD_simd);
6456 }
6457 break;
6458 case OMPD_distribute:
6459 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6460 EndLoc, VarsWithInheritedDSA);
6461 break;
6462 case OMPD_target_update:
6463 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6464 EndLoc, AStmt);
6465 AllowedNameModifiers.push_back(OMPD_target_update);
6466 break;
6467 case OMPD_distribute_parallel_for:
6468 Res = ActOnOpenMPDistributeParallelForDirective(
6469 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6470 AllowedNameModifiers.push_back(OMPD_parallel);
6471 break;
6472 case OMPD_distribute_parallel_for_simd:
6473 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6474 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6475 AllowedNameModifiers.push_back(OMPD_parallel);
6476 if (LangOpts.OpenMP >= 50)
6477 AllowedNameModifiers.push_back(OMPD_simd);
6478 break;
6479 case OMPD_distribute_simd:
6480 Res = ActOnOpenMPDistributeSimdDirective(
6481 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6482 if (LangOpts.OpenMP >= 50)
6483 AllowedNameModifiers.push_back(OMPD_simd);
6484 break;
6485 case OMPD_target_parallel_for_simd:
6486 Res = ActOnOpenMPTargetParallelForSimdDirective(
6487 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6488 AllowedNameModifiers.push_back(OMPD_target);
6489 AllowedNameModifiers.push_back(OMPD_parallel);
6490 if (LangOpts.OpenMP >= 50)
6491 AllowedNameModifiers.push_back(OMPD_simd);
6492 break;
6493 case OMPD_target_simd:
6494 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6495 EndLoc, VarsWithInheritedDSA);
6496 AllowedNameModifiers.push_back(OMPD_target);
6497 if (LangOpts.OpenMP >= 50)
6498 AllowedNameModifiers.push_back(OMPD_simd);
6499 break;
6500 case OMPD_teams_distribute:
6501 Res = ActOnOpenMPTeamsDistributeDirective(
6502 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6503 break;
6504 case OMPD_teams_distribute_simd:
6505 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6506 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6507 if (LangOpts.OpenMP >= 50)
6508 AllowedNameModifiers.push_back(OMPD_simd);
6509 break;
6510 case OMPD_teams_distribute_parallel_for_simd:
6511 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6512 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6513 AllowedNameModifiers.push_back(OMPD_parallel);
6514 if (LangOpts.OpenMP >= 50)
6515 AllowedNameModifiers.push_back(OMPD_simd);
6516 break;
6517 case OMPD_teams_distribute_parallel_for:
6518 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6519 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6520 AllowedNameModifiers.push_back(OMPD_parallel);
6521 break;
6522 case OMPD_target_teams:
6523 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6524 EndLoc);
6525 AllowedNameModifiers.push_back(OMPD_target);
6526 break;
6527 case OMPD_target_teams_distribute:
6528 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6529 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6530 AllowedNameModifiers.push_back(OMPD_target);
6531 break;
6532 case OMPD_target_teams_distribute_parallel_for:
6533 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6534 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6535 AllowedNameModifiers.push_back(OMPD_target);
6536 AllowedNameModifiers.push_back(OMPD_parallel);
6537 break;
6538 case OMPD_target_teams_distribute_parallel_for_simd:
6539 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6540 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6541 AllowedNameModifiers.push_back(OMPD_target);
6542 AllowedNameModifiers.push_back(OMPD_parallel);
6543 if (LangOpts.OpenMP >= 50)
6544 AllowedNameModifiers.push_back(OMPD_simd);
6545 break;
6546 case OMPD_target_teams_distribute_simd:
6547 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6548 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6549 AllowedNameModifiers.push_back(OMPD_target);
6550 if (LangOpts.OpenMP >= 50)
6551 AllowedNameModifiers.push_back(OMPD_simd);
6552 break;
6553 case OMPD_interop:
6554 assert(AStmt == nullptr &&
6555 "No associated statement allowed for 'omp interop' directive");
6556 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6557 break;
6558 case OMPD_dispatch:
6559 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6560 EndLoc);
6561 break;
6562 case OMPD_loop:
6563 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6564 EndLoc, VarsWithInheritedDSA);
6565 break;
6566 case OMPD_teams_loop:
6567 Res = ActOnOpenMPTeamsGenericLoopDirective(
6568 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6569 break;
6570 case OMPD_target_teams_loop:
6571 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6572 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6573 break;
6574 case OMPD_parallel_loop:
6575 Res = ActOnOpenMPParallelGenericLoopDirective(
6576 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6577 break;
6578 case OMPD_target_parallel_loop:
6579 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6580 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6581 break;
6582 case OMPD_declare_target:
6583 case OMPD_end_declare_target:
6584 case OMPD_threadprivate:
6585 case OMPD_allocate:
6586 case OMPD_declare_reduction:
6587 case OMPD_declare_mapper:
6588 case OMPD_declare_simd:
6589 case OMPD_requires:
6590 case OMPD_declare_variant:
6591 case OMPD_begin_declare_variant:
6592 case OMPD_end_declare_variant:
6593 llvm_unreachable("OpenMP Directive is not allowed");
6594 case OMPD_unknown:
6595 default:
6596 llvm_unreachable("Unknown OpenMP directive");
6597 }
6598
6599 ErrorFound = Res.isInvalid() || ErrorFound;
6600
6601 // Check variables in the clauses if default(none) or
6602 // default(firstprivate) was specified.
6603 if (DSAStack->getDefaultDSA() == DSA_none ||
6604 DSAStack->getDefaultDSA() == DSA_private ||
6605 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6606 DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
6607 for (OMPClause *C : Clauses) {
6608 switch (C->getClauseKind()) {
6609 case OMPC_num_threads:
6610 case OMPC_dist_schedule:
6611 // Do not analyse if no parent teams directive.
6612 if (isOpenMPTeamsDirective(Kind))
6613 break;
6614 continue;
6615 case OMPC_if:
6616 if (isOpenMPTeamsDirective(Kind) &&
6617 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6618 break;
6619 if (isOpenMPParallelDirective(Kind) &&
6621 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6622 break;
6623 continue;
6624 case OMPC_schedule:
6625 case OMPC_detach:
6626 break;
6627 case OMPC_grainsize:
6628 case OMPC_num_tasks:
6629 case OMPC_final:
6630 case OMPC_priority:
6631 case OMPC_novariants:
6632 case OMPC_nocontext:
6633 // Do not analyze if no parent parallel directive.
6634 if (isOpenMPParallelDirective(Kind))
6635 break;
6636 continue;
6637 case OMPC_ordered:
6638 case OMPC_device:
6639 case OMPC_num_teams:
6640 case OMPC_thread_limit:
6641 case OMPC_hint:
6642 case OMPC_collapse:
6643 case OMPC_safelen:
6644 case OMPC_simdlen:
6645 case OMPC_sizes:
6646 case OMPC_default:
6647 case OMPC_proc_bind:
6648 case OMPC_private:
6649 case OMPC_firstprivate:
6650 case OMPC_lastprivate:
6651 case OMPC_shared:
6652 case OMPC_reduction:
6653 case OMPC_task_reduction:
6654 case OMPC_in_reduction:
6655 case OMPC_linear:
6656 case OMPC_aligned:
6657 case OMPC_copyin:
6658 case OMPC_copyprivate:
6659 case OMPC_nowait:
6660 case OMPC_untied:
6661 case OMPC_mergeable:
6662 case OMPC_allocate:
6663 case OMPC_read:
6664 case OMPC_write:
6665 case OMPC_update:
6666 case OMPC_capture:
6667 case OMPC_compare:
6668 case OMPC_seq_cst:
6669 case OMPC_acq_rel:
6670 case OMPC_acquire:
6671 case OMPC_release:
6672 case OMPC_relaxed:
6673 case OMPC_depend:
6674 case OMPC_threads:
6675 case OMPC_simd:
6676 case OMPC_map:
6677 case OMPC_nogroup:
6678 case OMPC_defaultmap:
6679 case OMPC_to:
6680 case OMPC_from:
6681 case OMPC_use_device_ptr:
6682 case OMPC_use_device_addr:
6683 case OMPC_is_device_ptr:
6684 case OMPC_has_device_addr:
6685 case OMPC_nontemporal:
6686 case OMPC_order:
6687 case OMPC_destroy:
6688 case OMPC_inclusive:
6689 case OMPC_exclusive:
6690 case OMPC_uses_allocators:
6691 case OMPC_affinity:
6692 case OMPC_bind:
6693 case OMPC_filter:
6694 continue;
6695 case OMPC_allocator:
6696 case OMPC_flush:
6697 case OMPC_depobj:
6698 case OMPC_threadprivate:
6699 case OMPC_uniform:
6700 case OMPC_unknown:
6701 case OMPC_unified_address:
6702 case OMPC_unified_shared_memory:
6703 case OMPC_reverse_offload:
6704 case OMPC_dynamic_allocators:
6705 case OMPC_atomic_default_mem_order:
6706 case OMPC_device_type:
6707 case OMPC_match:
6708 case OMPC_when:
6709 default:
6710 llvm_unreachable("Unexpected clause");
6711 }
6712 for (Stmt *CC : C->children()) {
6713 if (CC)
6714 DSAChecker.Visit(CC);
6715 }
6716 }
6717 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6718 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6719 }
6720 for (const auto &P : VarsWithInheritedDSA) {
6721 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6722 continue;
6723 ErrorFound = true;
6724 if (DSAStack->getDefaultDSA() == DSA_none ||
6725 DSAStack->getDefaultDSA() == DSA_private ||
6726 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6727 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6728 << P.first << P.second->getSourceRange();
6729 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6730 } else if (getLangOpts().OpenMP >= 50) {
6731 Diag(P.second->getExprLoc(),
6732 diag::err_omp_defaultmap_no_attr_for_variable)
6733 << P.first << P.second->getSourceRange();
6734 Diag(DSAStack->getDefaultDSALocation(),
6735 diag::note_omp_defaultmap_attr_none);
6736 }
6737 }
6738
6739 if (!AllowedNameModifiers.empty())
6740 ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
6741 ErrorFound;
6742
6743 if (ErrorFound)
6744 return StmtError();
6745
6746 if (!CurContext->isDependentContext() &&
6748 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6749 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6750 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6751 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6752 // Register target to DSA Stack.
6753 DSAStack->addTargetDirLocation(StartLoc);
6754 }
6755
6756 return Res;
6757}
6758
6760 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6761 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6762 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6763 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6764 assert(Aligneds.size() == Alignments.size());
6765 assert(Linears.size() == LinModifiers.size());
6766 assert(Linears.size() == Steps.size());
6767 if (!DG || DG.get().isNull())
6768 return DeclGroupPtrTy();
6769
6770 const int SimdId = 0;
6771 if (!DG.get().isSingleDecl()) {
6772 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6773 << SimdId;
6774 return DG;
6775 }
6776 Decl *ADecl = DG.get().getSingleDecl();
6777 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6778 ADecl = FTD->getTemplatedDecl();
6779
6780 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6781 if (!FD) {
6782 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6783 return DeclGroupPtrTy();
6784 }
6785
6786 // OpenMP [2.8.2, declare simd construct, Description]
6787 // The parameter of the simdlen clause must be a constant positive integer
6788 // expression.
6789 ExprResult SL;
6790 if (Simdlen)
6791 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6792 // OpenMP [2.8.2, declare simd construct, Description]
6793 // The special this pointer can be used as if was one of the arguments to the
6794 // function in any of the linear, aligned, or uniform clauses.
6795 // The uniform clause declares one or more arguments to have an invariant
6796 // value for all concurrent invocations of the function in the execution of a
6797 // single SIMD loop.
6798 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6799 const Expr *UniformedLinearThis = nullptr;
6800 for (const Expr *E : Uniforms) {
6801 E = E->IgnoreParenImpCasts();
6802 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6803 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6804 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6805 FD->getParamDecl(PVD->getFunctionScopeIndex())
6806 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6807 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6808 continue;
6809 }
6810 if (isa<CXXThisExpr>(E)) {
6811 UniformedLinearThis = E;
6812 continue;
6813 }
6814 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6815 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6816 }
6817 // OpenMP [2.8.2, declare simd construct, Description]
6818 // The aligned clause declares that the object to which each list item points
6819 // is aligned to the number of bytes expressed in the optional parameter of
6820 // the aligned clause.
6821 // The special this pointer can be used as if was one of the arguments to the
6822 // function in any of the linear, aligned, or uniform clauses.
6823 // The type of list items appearing in the aligned clause must be array,
6824 // pointer, reference to array, or reference to pointer.
6825 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6826 const Expr *AlignedThis = nullptr;
6827 for (const Expr *E : Aligneds) {
6828 E = E->IgnoreParenImpCasts();
6829 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6830 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6831 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6832 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6833 FD->getParamDecl(PVD->getFunctionScopeIndex())
6834 ->getCanonicalDecl() == CanonPVD) {
6835 // OpenMP [2.8.1, simd construct, Restrictions]
6836 // A list-item cannot appear in more than one aligned clause.
6837 if (AlignedArgs.count(CanonPVD) > 0) {
6838 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6839 << 1 << getOpenMPClauseName(OMPC_aligned)
6840 << E->getSourceRange();
6841 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6842 diag::note_omp_explicit_dsa)
6843 << getOpenMPClauseName(OMPC_aligned);
6844 continue;
6845 }
6846 AlignedArgs[CanonPVD] = E;
6847 QualType QTy = PVD->getType()
6848 .getNonReferenceType()
6849 .getUnqualifiedType()
6850 .getCanonicalType();
6851 const Type *Ty = QTy.getTypePtrOrNull();
6852 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6853 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6854 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6855 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6856 }
6857 continue;
6858 }
6859 }
6860 if (isa<CXXThisExpr>(E)) {
6861 if (AlignedThis) {
6862 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6863 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6864 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6865 << getOpenMPClauseName(OMPC_aligned);
6866 }
6867 AlignedThis = E;
6868 continue;
6869 }
6870 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6871 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6872 }
6873 // The optional parameter of the aligned clause, alignment, must be a constant
6874 // positive integer expression. If no optional parameter is specified,
6875 // implementation-defined default alignments for SIMD instructions on the
6876 // target platforms are assumed.
6878 for (Expr *E : Alignments) {
6879 ExprResult Align;
6880 if (E)
6881 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6882 NewAligns.push_back(Align.get());
6883 }
6884 // OpenMP [2.8.2, declare simd construct, Description]
6885 // The linear clause declares one or more list items to be private to a SIMD
6886 // lane and to have a linear relationship with respect to the iteration space
6887 // of a loop.
6888 // The special this pointer can be used as if was one of the arguments to the
6889 // function in any of the linear, aligned, or uniform clauses.
6890 // When a linear-step expression is specified in a linear clause it must be
6891 // either a constant integer expression or an integer-typed parameter that is
6892 // specified in a uniform clause on the directive.
6893 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6894 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6895 auto MI = LinModifiers.begin();
6896 for (const Expr *E : Linears) {
6897 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6898 ++MI;
6899 E = E->IgnoreParenImpCasts();
6900 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6901 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6902 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6903 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6904 FD->getParamDecl(PVD->getFunctionScopeIndex())
6905 ->getCanonicalDecl() == CanonPVD) {
6906 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6907 // A list-item cannot appear in more than one linear clause.
6908 if (LinearArgs.count(CanonPVD) > 0) {
6909 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6910 << getOpenMPClauseName(OMPC_linear)
6911 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6912 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6913 diag::note_omp_explicit_dsa)
6914 << getOpenMPClauseName(OMPC_linear);
6915 continue;
6916 }
6917 // Each argument can appear in at most one uniform or linear clause.
6918 if (UniformedArgs.count(CanonPVD) > 0) {
6919 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6920 << getOpenMPClauseName(OMPC_linear)
6921 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6922 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6923 diag::note_omp_explicit_dsa)
6924 << getOpenMPClauseName(OMPC_uniform);
6925 continue;
6926 }
6927 LinearArgs[CanonPVD] = E;
6928 if (E->isValueDependent() || E->isTypeDependent() ||
6931 continue;
6932 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6933 PVD->getOriginalType(),
6934 /*IsDeclareSimd=*/true);
6935 continue;
6936 }
6937 }
6938 if (isa<CXXThisExpr>(E)) {
6939 if (UniformedLinearThis) {
6940 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6941 << getOpenMPClauseName(OMPC_linear)
6942 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6943 << E->getSourceRange();
6944 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6945 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6946 : OMPC_linear);
6947 continue;
6948 }
6949 UniformedLinearThis = E;
6950 if (E->isValueDependent() || E->isTypeDependent() ||
6952 continue;
6953 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6954 E->getType(), /*IsDeclareSimd=*/true);
6955 continue;
6956 }
6957 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6958 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6959 }
6960 Expr *Step = nullptr;
6961 Expr *NewStep = nullptr;
6962 SmallVector<Expr *, 4> NewSteps;
6963 for (Expr *E : Steps) {
6964 // Skip the same step expression, it was checked already.
6965 if (Step == E || !E) {
6966 NewSteps.push_back(E ? NewStep : nullptr);
6967 continue;
6968 }
6969 Step = E;
6970 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6971 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6972 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6973 if (UniformedArgs.count(CanonPVD) == 0) {
6974 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6975 << Step->getSourceRange();
6976 } else if (E->isValueDependent() || E->isTypeDependent() ||
6979 CanonPVD->getType()->hasIntegerRepresentation()) {
6980 NewSteps.push_back(Step);
6981 } else {
6982 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6983 << Step->getSourceRange();
6984 }
6985 continue;
6986 }
6987 NewStep = Step;
6988 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6989 !Step->isInstantiationDependent() &&
6991 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6992 .get();
6993 if (NewStep)
6994 NewStep =
6995 VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
6996 }
6997 NewSteps.push_back(NewStep);
6998 }
6999 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7000 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7001 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7002 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7003 const_cast<Expr **>(Linears.data()), Linears.size(),
7004 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7005 NewSteps.data(), NewSteps.size(), SR);
7006 ADecl->addAttr(NewAttr);
7007 return DG;
7008}
7009
7010static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7011 QualType NewType) {
7012 assert(NewType->isFunctionProtoType() &&
7013 "Expected function type with prototype.");
7014 assert(FD->getType()->isFunctionNoProtoType() &&
7015 "Expected function with type with no prototype.");
7016 assert(FDWithProto->getType()->isFunctionProtoType() &&
7017 "Expected function with prototype.");
7018 // Synthesize parameters with the same types.
7019 FD->setType(NewType);
7021 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7022 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7023 SourceLocation(), nullptr, P->getType(),
7024 /*TInfo=*/nullptr, SC_None, nullptr);
7025 Param->setScopeInfo(0, Params.size());
7026 Param->setImplicit();
7027 Params.push_back(Param);
7028 }
7029
7030 FD->setParams(Params);
7031}
7032
7034 if (D->isInvalidDecl())
7035 return;
7036 FunctionDecl *FD = nullptr;
7037 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7038 FD = UTemplDecl->getTemplatedDecl();
7039 else
7040 FD = cast<FunctionDecl>(D);
7041 assert(FD && "Expected a function declaration!");
7042
7043 // If we are instantiating templates we do *not* apply scoped assumptions but
7044 // only global ones. We apply scoped assumption to the template definition
7045 // though.
7046 if (!inTemplateInstantiation()) {
7047 for (AssumptionAttr *AA : OMPAssumeScoped)
7048 FD->addAttr(AA);
7049 }
7050 for (AssumptionAttr *AA : OMPAssumeGlobal)
7051 FD->addAttr(AA);
7052}
7053
7054Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7055 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7056
7058 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7060 if (!D.getIdentifier())
7061 return;
7062
7063 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7064
7065 // Template specialization is an extension, check if we do it.
7066 bool IsTemplated = !TemplateParamLists.empty();
7067 if (IsTemplated &
7068 !DVScope.TI->isExtensionActive(
7069 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7070 return;
7071
7072 IdentifierInfo *BaseII = D.getIdentifier();
7073 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7075 LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7076
7077 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
7078 QualType FType = TInfo->getType();
7079
7080 bool IsConstexpr =
7082 bool IsConsteval =
7084
7085 for (auto *Candidate : Lookup) {
7086 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7087 FunctionDecl *UDecl = nullptr;
7088 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7089 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7090 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7091 UDecl = FTD->getTemplatedDecl();
7092 } else if (!IsTemplated)
7093 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7094 if (!UDecl)
7095 continue;
7096
7097 // Don't specialize constexpr/consteval functions with
7098 // non-constexpr/consteval functions.
7099 if (UDecl->isConstexpr() && !IsConstexpr)
7100 continue;
7101 if (UDecl->isConsteval() && !IsConsteval)
7102 continue;
7103
7104 QualType UDeclTy = UDecl->getType();
7105 if (!UDeclTy->isDependentType()) {
7107 FType, UDeclTy, /* OfBlockPointer */ false,
7108 /* Unqualified */ false, /* AllowCXX */ true);
7109 if (NewType.isNull())
7110 continue;
7111 }
7112
7113 // Found a base!
7114 Bases.push_back(UDecl);
7115 }
7116
7117 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7118 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7119 // If no base was found we create a declaration that we use as base.
7120 if (Bases.empty() && UseImplicitBase) {
7122 Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
7123 BaseD->setImplicit(true);
7124 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7125 Bases.push_back(BaseTemplD->getTemplatedDecl());
7126 else
7127 Bases.push_back(cast<FunctionDecl>(BaseD));
7128 }
7129
7130 std::string MangledName;
7131 MangledName += D.getIdentifier()->getName();
7132 MangledName += getOpenMPVariantManglingSeparatorStr();
7133 MangledName += DVScope.NameSuffix;
7134 IdentifierInfo &VariantII = Context.Idents.get(MangledName);
7135
7136 VariantII.setMangledOpenMPVariantName(true);
7137 D.SetIdentifier(&VariantII, D.getBeginLoc());
7138}
7139
7142 // Do not mark function as is used to prevent its emission if this is the
7143 // only place where it is used.
7146
7147 FunctionDecl *FD = nullptr;
7148 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7149 FD = UTemplDecl->getTemplatedDecl();
7150 else
7151 FD = cast<FunctionDecl>(D);
7152 auto *VariantFuncRef = DeclRefExpr::Create(
7154 /* RefersToEnclosingVariableOrCapture */ false,
7155 /* NameLoc */ FD->getLocation(), FD->getType(),
7157
7158 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7159 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7160 Context, VariantFuncRef, DVScope.TI,
7161 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7162 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7163 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7164 for (FunctionDecl *BaseFD : Bases)
7165 BaseFD->addAttr(OMPDeclareVariantA);
7166}
7167
7169 SourceLocation LParenLoc,
7170 MultiExprArg ArgExprs,
7171 SourceLocation RParenLoc, Expr *ExecConfig) {
7172 // The common case is a regular call we do not want to specialize at all. Try
7173 // to make that case fast by bailing early.
7174 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7175 if (!CE)
7176 return Call;
7177
7178 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7179 if (!CalleeFnDecl)
7180 return Call;
7181
7182 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7183 return Call;
7184
7186 std::function<void(StringRef)> DiagUnknownTrait = [this,
7187 CE](StringRef ISATrait) {
7188 // TODO Track the selector locations in a way that is accessible here to
7189 // improve the diagnostic location.
7190 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7191 << ISATrait;
7192 };
7193 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7194 getCurFunctionDecl(), DSAStack->getConstructTraits());
7195
7196 QualType CalleeFnType = CalleeFnDecl->getType();
7197
7200 while (CalleeFnDecl) {
7201 for (OMPDeclareVariantAttr *A :
7202 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7203 Expr *VariantRef = A->getVariantFuncRef();
7204
7205 VariantMatchInfo VMI;
7206 OMPTraitInfo &TI = A->getTraitInfo();
7208 if (!isVariantApplicableInContext(VMI, OMPCtx,
7209 /* DeviceSetOnly */ false))
7210 continue;
7211
7212 VMIs.push_back(VMI);
7213 Exprs.push_back(VariantRef);
7214 }
7215
7216 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7217 }
7218
7219 ExprResult NewCall;
7220 do {
7221 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7222 if (BestIdx < 0)
7223 return Call;
7224 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7225 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7226
7227 {
7228 // Try to build a (member) call expression for the current best applicable
7229 // variant expression. We allow this to fail in which case we continue
7230 // with the next best variant expression. The fail case is part of the
7231 // implementation defined behavior in the OpenMP standard when it talks
7232 // about what differences in the function prototypes: "Any differences
7233 // that the specific OpenMP context requires in the prototype of the
7234 // variant from the base function prototype are implementation defined."
7235 // This wording is there to allow the specialized variant to have a
7236 // different type than the base function. This is intended and OK but if
7237 // we cannot create a call the difference is not in the "implementation
7238 // defined range" we allow.
7239 Sema::TentativeAnalysisScope Trap(*this);
7240
7241 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7242 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7243 BestExpr = MemberExpr::CreateImplicit(
7244 Context, MemberCall->getImplicitObjectArgument(),
7245 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7246 MemberCall->getValueKind(), MemberCall->getObjectKind());
7247 }
7248 NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
7249 ExecConfig);
7250 if (NewCall.isUsable()) {
7251 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7252 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7254 CalleeFnType, NewCalleeFnDecl->getType(),
7255 /* OfBlockPointer */ false,
7256 /* Unqualified */ false, /* AllowCXX */ true);
7257 if (!NewType.isNull())
7258 break;
7259 // Don't use the call if the function type was not compatible.
7260 NewCall = nullptr;
7261 }
7262 }
7263 }
7264
7265 VMIs.erase(VMIs.begin() + BestIdx);
7266 Exprs.erase(Exprs.begin() + BestIdx);
7267 } while (!VMIs.empty());
7268
7269 if (!NewCall.isUsable())
7270 return Call;
7271 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7272}
7273
7276 Expr *VariantRef, OMPTraitInfo &TI,
7277 unsigned NumAppendArgs,
7278 SourceRange SR) {
7279 if (!DG || DG.get().isNull())
7280 return None;
7281
7282 const int VariantId = 1;
7283 // Must be applied only to single decl.
7284 if (!DG.get().isSingleDecl()) {
7285 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7286 << VariantId << SR;
7287 return None;
7288 }
7289 Decl *ADecl = DG.get().getSingleDecl();
7290 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7291 ADecl = FTD->getTemplatedDecl();
7292
7293 // Decl must be a function.
7294 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7295 if (!FD) {
7296 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7297 << VariantId << SR;
7298 return None;
7299 }
7300
7301 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7302 // The 'target' attribute needs to be separately checked because it does
7303 // not always signify a multiversion function declaration.
7304 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7305 };
7306 // OpenMP is not compatible with multiversion function attributes.
7307 if (HasMultiVersionAttributes(FD)) {
7308 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7309 << SR;
7310 return None;
7311 }
7312
7313 // Allow #pragma omp declare variant only if the function is not used.
7314 if (FD->isUsed(false))
7315 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7316 << FD->getLocation();
7317
7318 // Check if the function was emitted already.
7319 const FunctionDecl *Definition;
7320 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7321 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7322 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7323 << FD->getLocation();
7324
7325 // The VariantRef must point to function.
7326 if (!VariantRef) {
7327 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7328 return None;
7329 }
7330
7331 auto ShouldDelayChecks = [](Expr *&E, bool) {
7332 return E && (E->isTypeDependent() || E->isValueDependent() ||
7335 };
7336 // Do not check templates, wait until instantiation.
7337 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7338 TI.anyScoreOrCondition(ShouldDelayChecks))
7339 return std::make_pair(FD, VariantRef);
7340
7341 // Deal with non-constant score and user condition expressions.
7342 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7343 bool IsScore) -> bool {
7344 if (!E || E->isIntegerConstantExpr(Context))
7345 return false;
7346
7347 if (IsScore) {
7348 // We warn on non-constant scores and pretend they were not present.
7349 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7350 << E;
7351 E = nullptr;
7352 } else {
7353 // We could replace a non-constant user condition with "false" but we
7354 // will soon need to handle these anyway for the dynamic version of
7355 // OpenMP context selectors.
7356 Diag(E->getExprLoc(),
7357 diag::err_omp_declare_variant_user_condition_not_constant)
7358 << E;
7359 }
7360 return true;
7361 };
7362 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7363 return None;
7364
7365 QualType AdjustedFnType = FD->getType();
7366 if (NumAppendArgs) {
7367 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7368 if (!PTy) {
7369 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7370 << SR;
7371 return None;
7372 }
7373 // Adjust the function type to account for an extra omp_interop_t for each
7374 // specified in the append_args clause.
7375 const TypeDecl *TD = nullptr;
7376 LookupResult Result(*this, &Context.Idents.get("omp_interop_t"),
7378 if (LookupName(Result, getCurScope())) {
7379 NamedDecl *ND = Result.getFoundDecl();
7380 TD = dyn_cast_or_null<TypeDecl>(ND);
7381 }
7382 if (!TD) {
7383 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7384 return None;
7385 }
7386 QualType InteropType = Context.getTypeDeclType(TD);
7387 if (PTy->isVariadic()) {
7388 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7389 return None;
7390 }
7392 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7393 Params.insert(Params.end(), NumAppendArgs, InteropType);
7394 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7395 PTy->getExtProtoInfo());
7396 }
7397
7398 // Convert VariantRef expression to the type of the original function to
7399 // resolve possible conflicts.
7400 ExprResult VariantRefCast = VariantRef;
7401 if (LangOpts.CPlusPlus) {
7402 QualType FnPtrType;
7403 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7404 if (Method && !Method->isStatic()) {
7405 const Type *ClassType =
7406 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7407 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7408 ExprResult ER;
7409 {
7410 // Build adrr_of unary op to correctly handle type checks for member
7411 // functions.
7412 Sema::TentativeAnalysisScope Trap(*this);
7413 ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7414 VariantRef);
7415 }
7416 if (!ER.isUsable()) {
7417 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7418 << VariantId << VariantRef->getSourceRange();
7419 return None;
7420 }
7421 VariantRef = ER.get();
7422 } else {
7423 FnPtrType = Context.getPointerType(AdjustedFnType);
7424 }
7425 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7426 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7428 VariantRef, FnPtrType.getUnqualifiedType(),
7429 /*SuppressUserConversions=*/false, AllowedExplicit::None,
7430 /*InOverloadResolution=*/false,
7431 /*CStyle=*/false,
7432 /*AllowObjCWritebackConversion=*/false);
7433 if (ICS.isFailure()) {
7434 Diag(VariantRef->getExprLoc(),
7435 diag::err_omp_declare_variant_incompat_types)
7436 << VariantRef->getType()
7437 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7438 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7439 return None;
7440 }
7441 VariantRefCast = PerformImplicitConversion(
7442 VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
7443 if (!VariantRefCast.isUsable())
7444 return None;
7445 }
7446 // Drop previously built artificial addr_of unary op for member functions.
7447 if (Method && !Method->isStatic()) {
7448 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7449 if (auto *UO = dyn_cast<UnaryOperator>(
7450 PossibleAddrOfVariantRef->IgnoreImplicit()))
7451 VariantRefCast = UO->getSubExpr();
7452 }
7453 }
7454
7455 ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
7456 if (!ER.isUsable() ||
7458 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7459 << VariantId << VariantRef->getSourceRange();
7460 return None;
7461 }
7462
7463 // The VariantRef must point to function.
7464 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7465 if (!DRE) {
7466 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7467 << VariantId << VariantRef->getSourceRange();
7468 return None;
7469 }
7470 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7471 if (!NewFD) {
7472 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7473 << VariantId << VariantRef->getSourceRange();
7474 return None;
7475 }
7476
7477 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7478 Diag(VariantRef->getExprLoc(),
7479 diag::err_omp_declare_variant_same_base_function)
7480 << VariantRef->getSourceRange();
7481 return None;
7482 }
7483
7484 // Check if function types are compatible in C.
7485 if (!LangOpts.CPlusPlus) {
7486 QualType NewType =
7487 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7488 if (NewType.isNull()) {
7489 Diag(VariantRef->getExprLoc(),
7490 diag::err_omp_declare_variant_incompat_types)
7491 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7492 << VariantRef->getSourceRange();
7493 return None;
7494 }
7495 if (NewType->isFunctionProtoType()) {
7496 if (FD->getType()->isFunctionNoProtoType())
7497 setPrototype(*this, FD, NewFD, NewType);
7498 else if (NewFD->getType()->isFunctionNoProtoType())
7499 setPrototype(*this, NewFD, FD, NewType);
7500 }
7501 }
7502
7503 // Check if variant function is not marked with declare variant directive.
7504 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7505 Diag(VariantRef->getExprLoc(),
7506 diag::warn_omp_declare_variant_marked_as_declare_variant)
7507 << VariantRef->getSourceRange();
7508 SourceRange SR =
7509 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7510 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7511 return None;
7512 }
7513
7514 enum DoesntSupport {
7515 VirtFuncs = 1,
7516 Constructors = 3,
7517 Destructors = 4,
7518 DeletedFuncs = 5,
7519 DefaultedFuncs = 6,
7520 ConstexprFuncs = 7,
7521 ConstevalFuncs = 8,
7522 };
7523 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7524 if (CXXFD->isVirtual()) {
7525 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7526 << VirtFuncs;
7527 return None;
7528 }
7529
7530 if (isa<CXXConstructorDecl>(FD)) {
7531 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7532 << Constructors;
7533 return None;
7534 }
7535
7536 if (isa<CXXDestructorDecl>(FD)) {
7537 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7538 << Destructors;
7539 return None;
7540 }
7541 }
7542
7543 if (FD->isDeleted()) {
7544 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7545 << DeletedFuncs;
7546 return None;
7547 }
7548
7549 if (FD->isDefaulted()) {
7550 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7551 << DefaultedFuncs;
7552 return None;
7553 }
7554
7555 if (FD->isConstexpr()) {
7556 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7557 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7558 return None;
7559 }
7560
7561 // Check general compatibility.
7567 VariantRef->getExprLoc(),
7568 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7569 PartialDiagnosticAt(VariantRef->getExprLoc(),
7570 PDiag(diag::err_omp_declare_variant_diff)
7571 << FD->getLocation()),
7572 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7573 /*CLinkageMayDiffer=*/true))
7574 return None;
7575 return std::make_pair(FD, cast<Expr>(DRE));
7576}
7577
7579 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7580 ArrayRef<Expr *> AdjustArgsNothing,
7581 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7583 SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc,
7584 SourceRange SR) {
7585
7586 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7587 // An adjust_args clause or append_args clause can only be specified if the
7588 // dispatch selector of the construct selector set appears in the match
7589 // clause.
7590
7591 SmallVector<Expr *, 8> AllAdjustArgs;
7592 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7593 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7594
7595 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7596 VariantMatchInfo VMI;
7598 if (!llvm::is_contained(
7599 VMI.ConstructTraits,
7600 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7601 if (!AllAdjustArgs.empty())
7602 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7603 << getOpenMPClauseName(OMPC_adjust_args);
7604 if (!AppendArgs.empty())
7605 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7606 << getOpenMPClauseName(OMPC_append_args);
7607 return;
7608 }
7609 }
7610
7611 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7612 // Each argument can only appear in a single adjust_args clause for each
7613 // declare variant directive.
7615
7616 for (Expr *E : AllAdjustArgs) {
7617 E = E->IgnoreParenImpCasts();
7618 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7619 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7620 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7621 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7622 FD->getParamDecl(PVD->getFunctionScopeIndex())
7623 ->getCanonicalDecl() == CanonPVD) {
7624 // It's a parameter of the function, check duplicates.
7625 if (!AdjustVars.insert(CanonPVD).second) {
7626 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7627 << PVD;
7628 return;
7629 }
7630 continue;
7631 }
7632 }
7633 }
7634 // Anything that is not a function parameter is an error.
7635 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7636 return;
7637 }
7638
7639 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7640 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7641 AdjustArgsNothing.size(),
7642 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7643 AdjustArgsNeedDevicePtr.size(),
7644 const_cast<OMPDeclareVariantAttr::InteropType *>(AppendArgs.data()),
7645 AppendArgs.size(), SR);
7646 FD->addAttr(NewAttr);
7647}
7648
7650 Stmt *AStmt,
7651 SourceLocation StartLoc,
7652 SourceLocation EndLoc) {
7653 if (!AStmt)
7654 return StmtError();
7655
7656 auto *CS = cast<CapturedStmt>(AStmt);
7657 // 1.2.2 OpenMP Language Terminology
7658 // Structured block - An executable statement with a single entry at the
7659 // top and a single exit at the bottom.
7660 // The point of exit cannot be a branch out of the structured block.
7661 // longjmp() and throw() must not violate the entry/exit criteria.
7662 CS->getCapturedDecl()->setNothrow();
7663
7665
7666 return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
7667 DSAStack->getTaskgroupReductionRef(),
7668 DSAStack->isCancelRegion());
7669}
7670
7671namespace {
7672/// Iteration space of a single for loop.
7673struct LoopIterationSpace final {
7674 /// True if the condition operator is the strict compare operator (<, > or
7675 /// !=).
7676 bool IsStrictCompare = false;
7677 /// Condition of the loop.
7678 Expr *PreCond = nullptr;
7679 /// This expression calculates the number of iterations in the loop.
7680 /// It is always possible to calculate it before starting the loop.
7681 Expr *NumIterations = nullptr;
7682 /// The loop counter variable.
7683 Expr *CounterVar = nullptr;
7684 /// Private loop counter variable.
7685 Expr *PrivateCounterVar = nullptr;
7686 /// This is initializer for the initial value of #CounterVar.
7687 Expr *CounterInit = nullptr;
7688 /// This is step for the #CounterVar used to generate its update:
7689 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7690 Expr *CounterStep = nullptr;
7691 /// Should step be subtracted?
7692 bool Subtract = false;
7693 /// Source range of the loop init.
7694 SourceRange InitSrcRange;
7695 /// Source range of the loop condition.
7696 SourceRange CondSrcRange;
7697 /// Source range of the loop increment.
7698 SourceRange IncSrcRange;
7699 /// Minimum value that can have the loop control variable. Used to support
7700 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7701 /// since only such variables can be used in non-loop invariant expressions.
7702 Expr *MinValue = nullptr;
7703 /// Maximum value that can have the loop control variable. Used to support
7704 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7705 /// since only such variables can be used in non-loop invariant expressions.
7706 Expr *MaxValue = nullptr;
7707 /// true, if the lower bound depends on the outer loop control var.
7708 bool IsNonRectangularLB = false;
7709 /// true, if the upper bound depends on the outer loop control var.
7710 bool IsNonRectangularUB = false;
7711 /// Index of the loop this loop depends on and forms non-rectangular loop
7712 /// nest.
7713 unsigned LoopDependentIdx = 0;
7714 /// Final condition for the non-rectangular loop nest support. It is used to
7715 /// check that the number of iterations for this particular counter must be
7716 /// finished.
7717 Expr *FinalCondition = nullptr;
7718};
7719
7720/// Helper class for checking canonical form of the OpenMP loops and
7721/// extracting iteration space of each loop in the loop nest, that will be used
7722/// for IR generation.
7723class OpenMPIterationSpaceChecker {
7724 /// Reference to Sema.
7725 Sema &SemaRef;
7726 /// Does the loop associated directive support non-rectangular loops?
7727 bool SupportsNonRectangular;
7728 /// Data-sharing stack.
7729 DSAStackTy &Stack;
7730 /// A location for diagnostics (when there is no some better location).
7731 SourceLocation DefaultLoc;
7732 /// A location for diagnostics (when increment is not compatible).
7733 SourceLocation ConditionLoc;
7734 /// A source location for referring to loop init later.
7735 SourceRange InitSrcRange;
7736 /// A source location for referring to condition later.
7737 SourceRange ConditionSrcRange;
7738 /// A source location for referring to increment later.
7739 SourceRange IncrementSrcRange;
7740 /// Loop variable.
7741 ValueDecl *LCDecl = nullptr;
7742 /// Reference to loop variable.
7743 Expr *LCRef = nullptr;
7744 /// Lower bound (initializer for the var).
7745 Expr *LB = nullptr;
7746 /// Upper bound.
7747 Expr *UB = nullptr;
7748 /// Loop step (increment).
7749 Expr *Step = nullptr;
7750 /// This flag is true when condition is one of:
7751 /// Var < UB
7752 /// Var <= UB
7753 /// UB > Var
7754 /// UB >= Var
7755 /// This will have no value when the condition is !=
7756 llvm::Optional<bool> TestIsLessOp;
7757 /// This flag is true when condition is strict ( < or > ).
7758 bool TestIsStrictOp = false;
7759 /// This flag is true when step is subtracted on each iteration.
7760 bool SubtractStep = false;
7761 /// The outer loop counter this loop depends on (if any).
7762 const ValueDecl *DepDecl = nullptr;
7763 /// Contains number of loop (starts from 1) on which loop counter init
7764 /// expression of this loop depends on.
7765 Optional<unsigned> InitDependOnLC;
7766 /// Contains number of loop (starts from 1) on which loop counter condition
7767 /// expression of this loop depends on.
7768 Optional<unsigned> CondDependOnLC;
7769 /// Checks if the provide statement depends on the loop counter.
7770 Optional<unsigned> doesDependOnLoopCounter(const Stmt *S, bool IsInitializer);
7771 /// Original condition required for checking of the exit condition for
7772 /// non-rectangular loop.
7773 Expr *Condition = nullptr;
7774
7775public:
7776 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7777 DSAStackTy &Stack, SourceLocation DefaultLoc)
7778 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7779 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7780 /// Check init-expr for canonical loop form and save loop counter
7781 /// variable - #Var and its initialization value - #LB.
7782 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7783 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7784 /// for less/greater and for strict/non-strict comparison.
7785 bool checkAndSetCond(Expr *S);
7786 /// Check incr-expr for canonical loop form and return true if it
7787 /// does not conform, otherwise save loop step (#Step).
7788 bool checkAndSetInc(Expr *S);
7789 /// Return the loop counter variable.
7790 ValueDecl *getLoopDecl() const { return LCDecl; }
7791 /// Return the reference expression to loop counter variable.
7792 Expr *getLoopDeclRefExpr() const { return LCRef; }
7793 /// Source range of the loop init.
7794 SourceRange getInitSrcRange() const { return InitSrcRange; }
7795 /// Source range of the loop condition.
7796 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7797 /// Source range of the loop increment.
7798 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7799 /// True if the step should be subtracted.
7800 bool shouldSubtractStep() const { return SubtractStep; }
7801 /// True, if the compare operator is strict (<, > or !=).
7802 bool isStrictTestOp() const { return TestIsStrictOp; }
7803 /// Build the expression to calculate the number of iterations.
7804 Expr *buildNumIterations(
7805 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7806 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7807 /// Build the precondition expression for the loops.
7808 Expr *
7809 buildPreCond(Scope *S, Expr *Cond,
7810 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7811 /// Build reference expression to the counter be used for codegen.
7812 DeclRefExpr *
7813 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7814 DSAStackTy &DSA) const;
7815 /// Build reference expression to the private counter be used for
7816 /// codegen.
7817 Expr *buildPrivateCounterVar() const;
7818 /// Build initialization of the counter be used for codegen.
7819 Expr *buildCounterInit() const;
7820 /// Build step of the counter be used for codegen.
7821 Expr *buildCounterStep() const;
7822 /// Build loop data with counter value for depend clauses in ordered
7823 /// directives.
7824 Expr *
7825 buildOrderedLoopData(Scope *S, Expr *Counter,
7826 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7827 SourceLocation Loc, Expr *Inc = nullptr,
7828 OverloadedOperatorKind OOK = OO_Amp);
7829 /// Builds the minimum value for the loop counter.
7830 std::pair<Expr *, Expr *> buildMinMaxValues(
7831 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7832 /// Builds final condition for the non-rectangular loops.
7833 Expr *buildFinalCondition(Scope *S) const;
7834 /// Return true if any expression is dependent.
7835 bool dependent() const;
7836 /// Returns true if the initializer forms non-rectangular loop.
7837 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7838 /// Returns true if the condition forms non-rectangular loop.
7839 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7840 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7841 unsigned getLoopDependentIdx() const {
7842 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7843 }
7844
7845private:
7846 /// Check the right-hand side of an assignment in the increment
7847 /// expression.
7848 bool checkAndSetIncRHS(Expr *RHS);
7849 /// Helper to set loop counter variable and its initializer.
7850 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7851 bool EmitDiags);
7852 /// Helper to set upper bound.
7853 bool setUB(Expr *NewUB, llvm::Optional<bool> LessOp, bool StrictOp,
7855 /// Helper to set loop increment.
7856 bool setStep(Expr *NewStep, bool Subtract);
7857};
7858
7859bool OpenMPIterationSpaceChecker::dependent() const {
7860 if (!LCDecl) {
7861 assert(!LB && !UB && !Step);
7862 return false;
7863 }
7864 return LCDecl->getType()->isDependentType() ||
7865 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7866 (Step && Step->isValueDependent());
7867}
7868
7869bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7870 Expr *NewLCRefExpr,
7871 Expr *NewLB, bool EmitDiags) {
7872 // State consistency checking to ensure correct usage.
7873 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7874 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7875 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7876 return true;
7877 LCDecl = getCanonicalDecl(NewLCDecl);
7878 LCRef = NewLCRefExpr;
7879 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7880 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7881 if ((Ctor->isCopyOrMoveConstructor() ||
7882 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7883 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7884 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7885 LB = NewLB;
7886 if (EmitDiags)
7887 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7888 return false;
7889}
7890
7891bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB,
7892 llvm::Optional<bool> LessOp,
7893 bool StrictOp, SourceRange SR,
7894 SourceLocation SL) {
7895 // State consistency checking to ensure correct usage.
7896 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7897 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7898 if (!NewUB || NewUB->containsErrors())
7899 return true;
7900 UB = NewUB;
7901 if (LessOp)
7902 TestIsLessOp = LessOp;
7903 TestIsStrictOp = StrictOp;
7904 ConditionSrcRange = SR;
7905 ConditionLoc = SL;
7906 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7907 return false;
7908}
7909
7910bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7911 // State consistency checking to ensure correct usage.
7912 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7913 if (!NewStep || NewStep->containsErrors())
7914 return true;
7915 if (!NewStep->isValueDependent()) {
7916 // Check that the step is integer expression.
7917 SourceLocation StepLoc = NewStep->getBeginLoc();
7919 StepLoc, getExprAsWritten(NewStep));
7920 if (Val.isInvalid())
7921 return true;
7922 NewStep = Val.get();
7923
7924 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7925 // If test-expr is of form var relational-op b and relational-op is < or
7926 // <= then incr-expr must cause var to increase on each iteration of the
7927 // loop. If test-expr is of form var relational-op b and relational-op is
7928 // > or >= then incr-expr must cause var to decrease on each iteration of
7929 // the loop.
7930 // If test-expr is of form b relational-op var and relational-op is < or
7931 // <= then incr-expr must cause var to decrease on each iteration of the
7932 // loop. If test-expr is of form b relational-op var and relational-op is
7933 // > or >= then incr-expr must cause var to increase on each iteration of
7934 // the loop.
7936 NewStep->getIntegerConstantExpr(SemaRef.Context);
7937 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7938 bool IsConstNeg =
7939 Result && Result->isSigned() && (Subtract != Result->isNegative());
7940 bool IsConstPos =
7941 Result && Result->isSigned() && (Subtract == Result->isNegative());
7942 bool IsConstZero = Result && !Result->getBoolValue();
7943
7944 // != with increment is treated as <; != with decrement is treated as >
7945 if (!TestIsLessOp)
7946 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7947 if (UB &&
7948 (IsConstZero ||
7949 (TestIsLessOp.value() ? (IsConstNeg || (IsUnsigned && Subtract))
7950 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7951 SemaRef.Diag(NewStep->getExprLoc(),
7952 diag::err_omp_loop_incr_not_compatible)
7953 << LCDecl << TestIsLessOp.value() << NewStep->getSourceRange();
7954 SemaRef.Diag(ConditionLoc,
7955 diag::note_omp_loop_cond_requres_compatible_incr)
7956 << TestIsLessOp.value() << ConditionSrcRange;
7957 return true;
7958 }
7959 if (TestIsLessOp.value() == Subtract) {
7960 NewStep =
7961 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
7962 .get();
7963 Subtract = !Subtract;
7964 }
7965 }
7966
7967 Step = NewStep;
7968 SubtractStep = Subtract;
7969 return false;
7970}
7971
7972namespace {
7973/// Checker for the non-rectangular loops. Checks if the initializer or
7974/// condition expression references loop counter variable.
7975class LoopCounterRefChecker final
7976 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
7977 Sema &SemaRef;
7978 DSAStackTy &Stack;
7979 const ValueDecl *CurLCDecl = nullptr;
7980 const ValueDecl *DepDecl = nullptr;
7981 const ValueDecl *PrevDepDecl = nullptr;
7982 bool IsInitializer = true;
7983 bool SupportsNonRectangular;
7984 unsigned BaseLoopId = 0;
7985 bool checkDecl(const Expr *E, const ValueDecl *VD) {
7986 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
7987 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7988 << (IsInitializer ? 0 : 1);
7989 return false;
7990 }
7991 const auto &&Data = Stack.isLoopControlVariable(VD);
7992 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
7993 // The type of the loop iterator on which we depend may not have a random
7994 // access iterator type.
7995 if (Data.first && VD->getType()->isRecordType()) {
7996 SmallString<128> Name;
7997 llvm::raw_svector_ostream OS(Name);
7998 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
7999 /*Qualified=*/true);
8000 SemaRef.Diag(E->getExprLoc(),
8001 diag::err_omp_wrong_dependency_iterator_type)
8002 << OS.str();
8003 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8004 return false;
8005 }
8006 if (Data.first && !SupportsNonRectangular) {
8007 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8008 return false;
8009 }
8010 if (Data.first &&
8011 (DepDecl || (PrevDepDecl &&
8012 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8013 if (!DepDecl && PrevDepDecl)
8014 DepDecl = PrevDepDecl;
8015 SmallString<128> Name;
8016 llvm::raw_svector_ostream OS(Name);
8017 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8018 /*Qualified=*/true);
8019 SemaRef.Diag(E->getExprLoc(),
8020 diag::err_omp_invariant_or_linear_dependency)
8021 << OS.str();
8022 return false;
8023 }
8024 if (Data.first) {
8025 DepDecl = VD;
8026 BaseLoopId = Data.first;
8027 }
8028 return Data.first;
8029 }
8030
8031public:
8032 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8033 const ValueDecl *VD = E->getDecl();
8034 if (isa<VarDecl>(VD))
8035 return checkDecl(E, VD);
8036 return false;
8037 }
8038 bool VisitMemberExpr(const MemberExpr *E) {
8039 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8040 const ValueDecl *VD = E->getMemberDecl();
8041 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8042 return checkDecl(E, VD);
8043 }
8044 return false;
8045 }
8046 bool VisitStmt(const Stmt *S) {
8047 bool Res = false;
8048 for (const Stmt *Child : S->children())
8049 Res = (Child && Visit(Child)) || Res;
8050 return Res;
8051 }
8052 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8053 const ValueDecl *CurLCDecl, bool IsInitializer,
8054 const ValueDecl *PrevDepDecl = nullptr,
8055 bool SupportsNonRectangular = true)
8056 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8057 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8058 SupportsNonRectangular(SupportsNonRectangular) {}
8059 unsigned getBaseLoopId() const {
8060 assert(CurLCDecl && "Expected loop dependency.");
8061 return BaseLoopId;
8062 }
8063 const ValueDecl *getDepDecl() const {
8064 assert(CurLCDecl && "Expected loop dependency.");
8065 return DepDecl;
8066 }
8067};
8068} // namespace
8069
8071OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8072 bool IsInitializer) {
8073 // Check for the non-rectangular loops.
8074 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8075 DepDecl, SupportsNonRectangular);
8076 if (LoopStmtChecker.Visit(S)) {
8077 DepDecl = LoopStmtChecker.getDepDecl();
8078 return LoopStmtChecker.getBaseLoopId();
8079 }
8080 return llvm::None;
8081}
8082
8083bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8084 // Check init-expr for canonical loop form and save loop counter
8085 // variable - #Var and its initialization value - #LB.
8086 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8087 // var = lb
8088 // integer-type var = lb
8089 // random-access-iterator-type var = lb
8090 // pointer-type var = lb
8091 //
8092 if (!S) {
8093 if (EmitDiags) {
8094 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8095 }
8096 return true;
8097 }
8098 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8099 if (!ExprTemp->cleanupsHaveSideEffects())
8100 S = ExprTemp->getSubExpr();
8101
8102 InitSrcRange = S->getSourceRange();
8103 if (Expr *E = dyn_cast<Expr>(S))
8104 S = E->IgnoreParens();
8105 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8106 if (BO->getOpcode() == BO_Assign) {
8107 Expr *LHS = BO->getLHS()->IgnoreParens();
8108 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8109 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8110 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8111 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8112 EmitDiags);
8113 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8114 }
8115 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8116 if (ME->isArrow() &&
8117 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8118 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8119 EmitDiags);
8120 }
8121 }
8122 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8123 if (DS->isSingleDecl()) {
8124 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8125 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8126 // Accept non-canonical init form here but emit ext. warning.
8127 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8128 SemaRef.Diag(S->getBeginLoc(),
8129 diag::ext_omp_loop_not_canonical_init)
8130 << S->getSourceRange();
8131 return setLCDeclAndLB(
8132 Var,
8133 buildDeclRefExpr(SemaRef, Var,
8134 Var->getType().getNonReferenceType(),
8135 DS->getBeginLoc()),
8136 Var->getInit(), EmitDiags);
8137 }
8138 }
8139 }
8140 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8141 if (CE->getOperator() == OO_Equal) {
8142 Expr *LHS = CE->getArg(0);
8143 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8144 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8145 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8146 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8147 EmitDiags);
8148 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8149 }
8150 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8151 if (ME->isArrow() &&
8152 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8153 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8154 EmitDiags);
8155 }
8156 }
8157 }
8158
8159 if (dependent() || SemaRef.CurContext->isDependentContext())
8160 return false;
8161 if (EmitDiags) {
8162 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8163 << S->getSourceRange();
8164 }
8165 return true;
8166}
8167
8168/// Ignore parenthesizes, implicit casts, copy constructor and return the
8169/// variable (which may be the loop variable) if possible.
8170static const ValueDecl *getInitLCDecl(const Expr *E) {
8171 if (!E)
8172 return nullptr;
8173 E = getExprAsWritten(E);
8174 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8175 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8176 if ((Ctor->isCopyOrMoveConstructor() ||
8177 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8178 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8179 E = CE->getArg(0)->IgnoreParenImpCasts();
8180 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8181 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8182 return getCanonicalDecl(VD);
8183 }
8184 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8185 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8186 return getCanonicalDecl(ME->getMemberDecl());
8187 return nullptr;
8188}
8189
8190bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8191 // Check test-expr for canonical form, save upper-bound UB, flags for
8192 // less/greater and for strict/non-strict comparison.
8193 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8194 // var relational-op b
8195 // b relational-op var
8196 //
8197 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8198 if (!S) {
8199 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8200 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8201 return true;
8202 }
8203 Condition = S;
8204 S = getExprAsWritten(S);
8205 SourceLocation CondLoc = S->getBeginLoc();
8206 auto &&CheckAndSetCond = [this, IneqCondIsCanonical](
8207 BinaryOperatorKind Opcode, const Expr *LHS,
8208 const Expr *RHS, SourceRange SR,
8210 if (BinaryOperator::isRelationalOp(Opcode)) {
8211 if (getInitLCDecl(LHS) == LCDecl)
8212 return setUB(const_cast<Expr *>(RHS),
8213 (Opcode == BO_LT || Opcode == BO_LE),
8214 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8215 if (getInitLCDecl(RHS) == LCDecl)
8216 return setUB(const_cast<Expr *>(LHS),
8217 (Opcode == BO_GT || Opcode == BO_GE),
8218 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8219 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8220 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8221 /*LessOp=*/llvm::None,
8222 /*StrictOp=*/true, SR, OpLoc);
8223 }
8224 return llvm::None;
8225 };
8227 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8228 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8229 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8230 RBO->getOperatorLoc());
8231 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8232 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8233 BO->getSourceRange(), BO->getOperatorLoc());
8234 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8235 if (CE->getNumArgs() == 2) {
8236 Res = CheckAndSetCond(
8237 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8238 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8239 }
8240 }
8241 if (Res)
8242 return *Res;
8243 if (dependent() || SemaRef.CurContext->isDependentContext())
8244 return false;
8245 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8246 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8247 return true;
8248}
8249
8250bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8251 // RHS of canonical loop form increment can be:
8252 // var + incr
8253 // incr + var
8254 // var - incr
8255 //
8256 RHS = RHS->IgnoreParenImpCasts();
8257 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8258 if (BO->isAdditiveOp()) {
8259 bool IsAdd = BO->getOpcode() == BO_Add;
8260 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8261 return setStep(BO->getRHS(), !IsAdd);
8262 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8263 return setStep(BO->getLHS(), /*Subtract=*/false);
8264 }
8265 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8266 bool IsAdd = CE->getOperator() == OO_Plus;
8267 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8268 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8269 return setStep(CE->getArg(1), !IsAdd);
8270 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8271 return setStep(CE->getArg(0), /*Subtract=*/false);
8272 }
8273 }
8274 if (dependent() || SemaRef.CurContext->isDependentContext())
8275 return false;
8276 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8277 << RHS->getSourceRange() << LCDecl;
8278 return true;
8279}
8280
8281bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8282 // Check incr-expr for canonical loop form and return true if it
8283 // does not conform.
8284 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8285 // ++var
8286 // var++
8287 // --var
8288 // var--
8289 // var += incr
8290 // var -= incr
8291 // var = var + incr
8292 // var = incr + var
8293 // var = var - incr
8294 //
8295 if (!S) {
8296 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8297 return true;
8298 }
8299 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8300 if (!ExprTemp->cleanupsHaveSideEffects())
8301 S = ExprTemp->getSubExpr();
8302
8303 IncrementSrcRange = S->getSourceRange();
8304 S = S->IgnoreParens();
8305 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8306 if (UO->isIncrementDecrementOp() &&
8307 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8308 return setStep(SemaRef
8309 .ActOnIntegerConstant(UO->getBeginLoc(),
8310 (UO->isDecrementOp() ? -1 : 1))
8311 .get(),
8312 /*Subtract=*/false);
8313 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8314 switch (BO->getOpcode()) {
8315 case BO_AddAssign:
8316 case BO_SubAssign:
8317 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8318 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8319 break;
8320 case BO_Assign:
8321 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8322 return checkAndSetIncRHS(BO->getRHS());
8323 break;
8324 default:
8325 break;
8326 }
8327 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8328 switch (CE->getOperator()) {
8329 case OO_PlusPlus:
8330 case OO_MinusMinus:
8331 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8332 return setStep(SemaRef
8333 .ActOnIntegerConstant(
8334 CE->getBeginLoc(),
8335 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8336 .get(),
8337 /*Subtract=*/false);
8338 break;
8339 case OO_PlusEqual:
8340 case OO_MinusEqual:
8341 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8342 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8343 break;
8344 case OO_Equal:
8345 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8346 return checkAndSetIncRHS(CE->getArg(1));
8347 break;
8348 default:
8349 break;
8350 }
8351 }
8352 if (dependent() || SemaRef.CurContext->isDependentContext())
8353 return false;
8354 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8355 << S->getSourceRange() << LCDecl;
8356 return true;
8357}
8358
8359static ExprResult
8360tryBuildCapture(Sema &SemaRef, Expr *Capture,
8361 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8362 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8363 return Capture;
8364 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8365 return SemaRef.PerformImplicitConversion(
8366 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8367 /*AllowExplicit=*/true);
8368 auto I = Captures.find(Capture);
8369 if (I != Captures.end())
8370 return buildCapture(SemaRef, Capture, I->second);
8371 DeclRefExpr *Ref = nullptr;
8372 ExprResult Res = buildCapture(SemaRef, Capture, Ref);
8373 Captures[Capture] = Ref;
8374 return Res;
8375}
8376
8377/// Calculate number of iterations, transforming to unsigned, if number of
8378/// iterations may be larger than the original type.
8379static Expr *
8380calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8381 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8382 bool TestIsStrictOp, bool RoundToStep,
8383 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8384 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
8385 if (!NewStep.isUsable())
8386 return nullptr;
8387 llvm::APSInt LRes, SRes;
8388 bool IsLowerConst = false, IsStepConst = false;
8389 if (Optional<llvm::APSInt> Res =
8390 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8391 LRes = *Res;
8392 IsLowerConst = true;
8393 }
8394 if (Optional<llvm::APSInt> Res =
8395 Step->getIntegerConstantExpr(SemaRef.Context)) {
8396 SRes = *Res;
8397 IsStepConst = true;
8398 }
8399 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8400 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8401 (TestIsStrictOp && LRes.isStrictlyPositive()));
8402 bool NeedToReorganize = false;
8403 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8404 if (!NoNeedToConvert && IsLowerConst &&
8405 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8406 NoNeedToConvert = true;
8407 if (RoundToStep) {
8408 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8409 ? LRes.getBitWidth()
8410 : SRes.getBitWidth();
8411 LRes = LRes.extend(BW + 1);
8412 LRes.setIsSigned(true);
8413 SRes = SRes.extend(BW + 1);
8414 SRes.setIsSigned(true);
8415 LRes -= SRes;
8416 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8417 LRes = LRes.trunc(BW);
8418 }
8419 if (TestIsStrictOp) {
8420 unsigned BW = LRes.getBitWidth();
8421 LRes = LRes.extend(BW + 1);
8422 LRes.setIsSigned(true);
8423 ++LRes;
8424 NoNeedToConvert =
8425 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8426 // truncate to the original bitwidth.
8427 LRes = LRes.trunc(BW);
8428 }
8429 NeedToReorganize = NoNeedToConvert;
8430 }
8431 llvm::APSInt URes;
8432 bool IsUpperConst = false;
8433 if (Optional<llvm::APSInt> Res =
8434 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8435 URes = *Res;
8436 IsUpperConst = true;
8437 }
8438 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8439 (!RoundToStep || IsStepConst)) {
8440 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8441 : URes.getBitWidth();
8442 LRes = LRes.extend(BW + 1);
8443 LRes.setIsSigned(true);
8444 URes = URes.extend(BW + 1);
8445 URes.setIsSigned(true);
8446 URes -= LRes;
8447 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8448 NeedToReorganize = NoNeedToConvert;
8449 }
8450 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8451 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8452 // unsigned.
8453 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8454 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8455 QualType LowerTy = Lower->getType();
8456 QualType UpperTy = Upper->getType();
8457 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8458 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8459 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8460 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8462 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8463 Upper =
8464 SemaRef
8466 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8468 .get();
8469 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8470 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8471 }
8472 }
8473 if (!Lower || !Upper || NewStep.isInvalid())
8474 return nullptr;
8475
8476 ExprResult Diff;
8477 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8478 // 1]).
8479 if (NeedToReorganize) {
8480 Diff = Lower;
8481
8482 if (RoundToStep) {
8483 // Lower - Step
8484 Diff =
8485 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8486 if (!Diff.isUsable())
8487 return nullptr;
8488 }
8489
8490 // Lower - Step [+ 1]
8491 if (TestIsStrictOp)
8492 Diff = SemaRef.BuildBinOp(
8493 S, DefaultLoc, BO_Add, Diff.get(),
8494 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8495 if (!Diff.isUsable())
8496 return nullptr;
8497
8498 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8499 if (!Diff.isUsable())
8500 return nullptr;
8501
8502 // Upper - (Lower - Step [+ 1]).
8503 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8504 if (!Diff.isUsable())
8505 return nullptr;
8506 } else {
8507 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8508
8509 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8510 // BuildBinOp already emitted error, this one is to point user to upper
8511 // and lower bound, and to tell what is passed to 'operator-'.
8512 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8513 << Upper->getSourceRange() << Lower->getSourceRange();
8514 return nullptr;
8515 }
8516
8517 if (!Diff.isUsable())
8518 return nullptr;
8519
8520 // Upper - Lower [- 1]
8521 if (TestIsStrictOp)
8522 Diff = SemaRef.BuildBinOp(
8523 S, DefaultLoc, BO_Sub, Diff.get(),
8524 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8525 if (!Diff.isUsable())
8526 return nullptr;
8527
8528 if (RoundToStep) {
8529 // Upper - Lower [- 1] + Step
8530 Diff =
8531 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8532 if (!Diff.isUsable())
8533 return nullptr;
8534 }
8535 }
8536
8537 // Parentheses (for dumping/debugging purposes only).
8538 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8539 if (!Diff.isUsable())
8540 return nullptr;
8541
8542 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8543 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8544 if (!Diff.isUsable())
8545 return nullptr;
8546
8547 return Diff.get();
8548}
8549
8550/// Build the expression to calculate the number of iterations.
8551Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8552 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8553 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8554 QualType VarType = LCDecl->getType().getNonReferenceType();
8555 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8556 !SemaRef.getLangOpts().CPlusPlus)
8557 return nullptr;
8558 Expr *LBVal = LB;
8559 Expr *UBVal = UB;
8560 // LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8561 // max(LB(MinVal), LB(MaxVal))
8562 if (InitDependOnLC) {
8563 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8564 if (!IS.MinValue || !IS.MaxValue)
8565 return nullptr;
8566 // OuterVar = Min
8567 ExprResult MinValue =
8568 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8569 if (!MinValue.isUsable())
8570 return nullptr;
8571
8572 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8573 IS.CounterVar, MinValue.get());
8574 if (!LBMinVal.isUsable())
8575 return nullptr;
8576 // OuterVar = Min, LBVal
8577 LBMinVal =
8578 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8579 if (!LBMinVal.isUsable())
8580 return nullptr;
8581 // (OuterVar = Min, LBVal)
8582 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8583 if (!LBMinVal.isUsable())
8584 return nullptr;
8585
8586 // OuterVar = Max
8587 ExprResult MaxValue =
8588 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8589 if (!MaxValue.isUsable())
8590 return nullptr;
8591
8592 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8593 IS.CounterVar, MaxValue.get());
8594 if (!LBMaxVal.isUsable())
8595 return nullptr;
8596 // OuterVar = Max, LBVal
8597 LBMaxVal =
8598 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8599 if (!LBMaxVal.isUsable())
8600 return nullptr;
8601 // (OuterVar = Max, LBVal)
8602 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8603 if (!LBMaxVal.isUsable())
8604 return nullptr;
8605
8606 Expr *LBMin = tryBuildCapture(SemaRef, LBMinVal.get(), Captures).get();
8607 Expr *LBMax = tryBuildCapture(SemaRef, LBMaxVal.get(), Captures).get();
8608 if (!LBMin || !LBMax)
8609 return nullptr;
8610 // LB(MinVal) < LB(MaxVal)
8611 ExprResult MinLessMaxRes =
8612 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8613 if (!MinLessMaxRes.isUsable())
8614 return nullptr;
8615 Expr *MinLessMax =
8616 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures).get();
8617 if (!MinLessMax)
8618 return nullptr;
8619 if (*TestIsLessOp) {
8620 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8621 // LB(MaxVal))
8622 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8623 MinLessMax, LBMin, LBMax);
8624 if (!MinLB.isUsable())
8625 return nullptr;
8626 LBVal = MinLB.get();
8627 } else {
8628 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8629 // LB(MaxVal))
8630 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8631 MinLessMax, LBMax, LBMin);
8632 if (!MaxLB.isUsable())
8633 return nullptr;
8634 LBVal = MaxLB.get();
8635 }
8636 }
8637 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8638 // min(UB(MinVal), UB(MaxVal))
8639 if (CondDependOnLC) {
8640 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8641 if (!IS.MinValue || !IS.MaxValue)
8642 return nullptr;
8643 // OuterVar = Min
8644 ExprResult MinValue =
8645 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8646 if (!MinValue.isUsable())
8647 return nullptr;
8648
8649 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8650 IS.CounterVar, MinValue.get());
8651 if (!UBMinVal.isUsable())
8652 return nullptr;
8653 // OuterVar = Min, UBVal
8654 UBMinVal =
8655 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8656 if (!UBMinVal.isUsable())
8657 return nullptr;
8658 // (OuterVar = Min, UBVal)
8659 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8660 if (!UBMinVal.isUsable())
8661 return nullptr;
8662
8663 // OuterVar = Max
8664 ExprResult MaxValue =
8665 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8666 if (!MaxValue.isUsable())
8667 return nullptr;
8668
8669 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8670 IS.CounterVar, MaxValue.get());
8671 if (!UBMaxVal.isUsable())
8672 return nullptr;
8673 // OuterVar = Max, UBVal
8674 UBMaxVal =
8675 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8676 if (!UBMaxVal.isUsable())
8677 return nullptr;
8678 // (OuterVar = Max, UBVal)
8679 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8680 if (!UBMaxVal.isUsable())
8681 return nullptr;
8682
8683 Expr *UBMin = tryBuildCapture(SemaRef, UBMinVal.get(), Captures).get();
8684 Expr *UBMax = tryBuildCapture(SemaRef, UBMaxVal.get(), Captures).get();
8685 if (!UBMin || !UBMax)
8686 return nullptr;
8687 // UB(MinVal) > UB(MaxVal)
8688 ExprResult MinGreaterMaxRes =
8689 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8690 if (!MinGreaterMaxRes.isUsable())
8691 return nullptr;
8692 Expr *MinGreaterMax =
8693 tryBuildCapture(SemaRef, MinGreaterMaxRes.get(), Captures).get();
8694 if (!MinGreaterMax)
8695 return nullptr;
8696 if (*TestIsLessOp) {
8697 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8698 // UB(MaxVal))
8699 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8700 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8701 if (!MaxUB.isUsable())
8702 return nullptr;
8703 UBVal = MaxUB.get();
8704 } else {
8705 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8706 // UB(MaxVal))
8707 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8708 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8709 if (!MinUB.isUsable())
8710 return nullptr;
8711 UBVal = MinUB.get();
8712 }
8713 }
8714 Expr *UBExpr = TestIsLessOp.value() ? UBVal : LBVal;
8715 Expr *LBExpr = TestIsLessOp.value() ? LBVal : UBVal;
8716 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get();
8717 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get();
8718 if (!Upper || !Lower)
8719 return nullptr;
8720
8721 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8722 Step, VarType, TestIsStrictOp,
8723 /*RoundToStep=*/true, Captures);
8724 if (!Diff.isUsable())
8725 return nullptr;
8726
8727 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8728 QualType Type = Diff.get()->getType();
8729 ASTContext &C = SemaRef.Context;
8730 bool UseVarType = VarType->hasIntegerRepresentation() &&
8731 C.getTypeSize(Type) > C.getTypeSize(VarType);
8732 if (!Type->isIntegerType() || UseVarType) {
8733 unsigned NewSize =
8734 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8735 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8737 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8738 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8739 Diff = SemaRef.PerformImplicitConversion(
8740 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8741 if (!Diff.isUsable())
8742 return nullptr;
8743 }
8744 }
8745 if (LimitedType) {
8746 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8747 if (NewSize != C.getTypeSize(Type)) {
8748 if (NewSize < C.getTypeSize(Type)) {
8749 assert(NewSize == 64 && "incorrect loop var size");
8750 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8751 << InitSrcRange << ConditionSrcRange;
8752 }
8753 QualType NewType = C.getIntTypeForBitwidth(
8755 C.getTypeSize(Type) < NewSize);
8756 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8757 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8758 Sema::AA_Converting, true);
8759 if (!Diff.isUsable())
8760 return nullptr;
8761 }
8762 }
8763 }
8764
8765 return Diff.get();
8766}
8767
8768std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8769 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8770 // Do not build for iterators, they cannot be used in non-rectangular loop
8771 // nests.
8772 if (LCDecl->getType()->isRecordType())
8773 return std::make_pair(nullptr, nullptr);
8774 // If we subtract, the min is in the condition, otherwise the min is in the
8775 // init value.
8776 Expr *MinExpr = nullptr;
8777 Expr *MaxExpr = nullptr;
8778 Expr *LBExpr = TestIsLessOp.value() ? LB : UB;
8779 Expr *UBExpr = TestIsLessOp.value() ? UB : LB;
8780 bool LBNonRect = TestIsLessOp.value() ? InitDependOnLC.has_value()
8781 : CondDependOnLC.has_value();
8782 bool UBNonRect = TestIsLessOp.value() ? CondDependOnLC.has_value()
8783 : InitDependOnLC.has_value();
8784 Expr *Lower =
8785 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8786 Expr *Upper =
8787 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8788 if (!Upper || !Lower)
8789 return std::make_pair(nullptr, nullptr);
8790
8791 if (*TestIsLessOp)
8792 MinExpr = Lower;
8793 else
8794 MaxExpr = Upper;
8795
8796 // Build minimum/maximum value based on number of iterations.
8797 QualType VarType = LCDecl->getType().getNonReferenceType();
8798
8799 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8800 Step, VarType, TestIsStrictOp,
8801 /*RoundToStep=*/false, Captures);
8802 if (!Diff.isUsable())
8803 return std::make_pair(nullptr, nullptr);
8804
8805 // ((Upper - Lower [- 1]) / Step) * Step
8806 // Parentheses (for dumping/debugging purposes only).
8807 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8808 if (!Diff.isUsable())
8809 return std::make_pair(nullptr, nullptr);
8810
8811 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
8812 if (!NewStep.isUsable())
8813 return std::make_pair(nullptr, nullptr);
8814 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8815 if (!Diff.isUsable())
8816 return std::make_pair(nullptr, nullptr);
8817
8818 // Parentheses (for dumping/debugging purposes only).
8819 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8820 if (!Diff.isUsable())
8821 return std::make_pair(nullptr, nullptr);
8822
8823 // Convert to the ptrdiff_t, if original type is pointer.
8824 if (VarType->isAnyPointerType() &&
8825 !SemaRef.Context.hasSameType(
8826 Diff.get()->getType(),
8828 Diff = SemaRef.PerformImplicitConversion(
8829 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8830 Sema::AA_Converting, /*AllowExplicit=*/true);
8831 }
8832 if (!Diff.isUsable())
8833 return std::make_pair(nullptr, nullptr);
8834
8835 if (*TestIsLessOp) {
8836 // MinExpr = Lower;
8837 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8838 Diff = SemaRef.BuildBinOp(
8839 S, DefaultLoc, BO_Add,
8840 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8841 Diff.get());
8842 if (!Diff.isUsable())
8843 return std::make_pair(nullptr, nullptr);
8844 } else {
8845 // MaxExpr = Upper;
8846 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8847 Diff = SemaRef.BuildBinOp(
8848 S, DefaultLoc, BO_Sub,
8849 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8850 Diff.get());
8851 if (!Diff.isUsable())
8852 return std::make_pair(nullptr, nullptr);
8853 }
8854
8855 // Convert to the original type.
8856 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8857 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8859 /*AllowExplicit=*/true);
8860 if (!Diff.isUsable())
8861 return std::make_pair(nullptr, nullptr);
8862
8863 Sema::TentativeAnalysisScope Trap(SemaRef);
8864 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8865 if (!Diff.isUsable())
8866 return std::make_pair(nullptr, nullptr);
8867
8868 if (*TestIsLessOp)
8869 MaxExpr = Diff.get();
8870 else
8871 MinExpr = Diff.get();
8872
8873 return std::make_pair(MinExpr, MaxExpr);
8874}
8875
8876Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8877 if (InitDependOnLC || CondDependOnLC)
8878 return Condition;
8879 return nullptr;
8880}
8881
8882Expr *OpenMPIterationSpaceChecker::buildPreCond(
8883 Scope *S, Expr *Cond,
8884 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8885 // Do not build a precondition when the condition/initialization is dependent
8886 // to prevent pessimistic early loop exit.
8887 // TODO: this can be improved by calculating min/max values but not sure that
8888 // it will be very effective.
8889 if (CondDependOnLC || InitDependOnLC)
8890 return SemaRef
8892 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8893 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8894 /*AllowExplicit=*/true)
8895 .get();
8896
8897 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8898 Sema::TentativeAnalysisScope Trap(SemaRef);
8899
8900 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8901 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8902 if (!NewLB.isUsable() || !NewUB.isUsable())
8903 return nullptr;
8904
8905 ExprResult CondExpr = SemaRef.BuildBinOp(
8906 S, DefaultLoc,
8907 TestIsLessOp.value() ? (TestIsStrictOp ? BO_LT : BO_LE)
8908 : (TestIsStrictOp ? BO_GT : BO_GE),
8909 NewLB.get(), NewUB.get());
8910 if (CondExpr.isUsable()) {
8911 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8912 SemaRef.Context.BoolTy))
8913 CondExpr = SemaRef.PerformImplicitConversion(
8914 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8915 /*AllowExplicit=*/true);
8916 }
8917
8918 // Otherwise use original loop condition and evaluate it in runtime.
8919 return CondExpr.isUsable() ? CondExpr.get() : Cond;
8920}
8921
8922/// Build reference expression to the counter be used for codegen.
8923DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8924 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8925 DSAStackTy &DSA) const {
8926 auto *VD = dyn_cast<VarDecl>(LCDecl);
8927 if (!VD) {
8928 VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
8930 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8931 const DSAStackTy::DSAVarData Data =
8932 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8933 // If the loop control decl is explicitly marked as private, do not mark it
8934 // as captured again.
8935 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
8936 Captures.insert(std::make_pair(LCRef, Ref));
8937 return Ref;
8938 }
8939 return cast<DeclRefExpr>(LCRef);
8940}
8941
8942Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
8943 if (LCDecl && !LCDecl->isInvalidDecl()) {
8945 VarDecl *PrivateVar = buildVarDecl(
8946 SemaRef, DefaultLoc, Type, LCDecl->getName(),
8947 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
8948 isa<VarDecl>(LCDecl)
8949 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
8950 : nullptr);
8951 if (PrivateVar->isInvalidDecl())
8952 return nullptr;
8953 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
8954 }
8955 return nullptr;
8956}
8957
8958/// Build initialization of the counter to be used for codegen.
8959Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
8960
8961/// Build step of the counter be used for codegen.
8962Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
8963
8964Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
8965 Scope *S, Expr *Counter,
8966 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
8967 Expr *Inc, OverloadedOperatorKind OOK) {
8968 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
8969 if (!Cnt)
8970 return nullptr;
8971 if (Inc) {
8972 assert((OOK == OO_Plus || OOK == OO_Minus) &&
8973 "Expected only + or - operations for depend clauses.");
8974 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
8975 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
8976 if (!Cnt)
8977 return nullptr;
8978 }
8979 QualType VarType = LCDecl->getType().getNonReferenceType();
8980 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8981 !SemaRef.getLangOpts().CPlusPlus)
8982 return nullptr;
8983 // Upper - Lower
8984 Expr *Upper =
8985 TestIsLessOp.value() ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
8986 Expr *Lower =
8987 TestIsLessOp.value() ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
8988 if (!Upper || !Lower)
8989 return nullptr;
8990
8991 ExprResult Diff = calculateNumIters(
8992 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
8993 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
8994 if (!Diff.isUsable())
8995 return nullptr;
8996
8997 return Diff.get();
8998}
8999} // namespace
9000
9002 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9003 assert(Init && "Expected loop in canonical form.");
9004 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9005 if (AssociatedLoops > 0 &&
9006 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9007 DSAStack->loopStart();
9008 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9009 *DSAStack, ForLoc);
9010 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9011 if (ValueDecl *D = ISC.getLoopDecl()) {
9012 auto *VD = dyn_cast<VarDecl>(D);
9013 DeclRefExpr *PrivateRef = nullptr;
9014 if (!VD) {
9015 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9016 VD = Private;
9017 } else {
9018 PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
9019 /*WithInit=*/false);
9020 VD = cast<VarDecl>(PrivateRef->getDecl());
9021 }
9022 }
9023 DSAStack->addLoopControlVariable(D, VD);
9024 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9025 if (LD != D->getCanonicalDecl()) {
9026 DSAStack->resetPossibleLoopCounter();
9027 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9029 buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9031 ForLoc, /*RefersToCapture=*/true));
9032 }
9033 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9034 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9035 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9036 // associated for-loop of a simd construct with just one associated
9037 // for-loop may be listed in a linear clause with a constant-linear-step
9038 // that is the increment of the associated for-loop. The loop iteration
9039 // variable(s) in the associated for-loop(s) of a for or parallel for
9040 // construct may be listed in a private or lastprivate clause.
9041 DSAStackTy::DSAVarData DVar =
9042 DSAStack->getTopDSA(D, /*FromParent=*/false);
9043 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9044 // is declared in the loop and it is predetermined as a private.
9045 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9046 OpenMPClauseKind PredeterminedCKind =
9048 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9049 : OMPC_private;
9050 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9051 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9052 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9053 DVar.CKind != OMPC_private))) ||
9054 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9055 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9056 DKind == OMPD_parallel_master_taskloop ||
9057 DKind == OMPD_parallel_masked_taskloop ||
9059 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9060 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9061 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9062 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9063 << getOpenMPClauseName(DVar.CKind)
9064 << getOpenMPDirectiveName(DKind)
9065 << getOpenMPClauseName(PredeterminedCKind);
9066 if (DVar.RefExpr == nullptr)
9067 DVar.CKind = PredeterminedCKind;
9068 reportOriginalDsa(*this, DSAStack, D, DVar,
9069 /*IsLoopIterVar=*/true);
9070 } else if (LoopDeclRefExpr) {
9071 // Make the loop iteration variable private (for worksharing
9072 // constructs), linear (for simd directives with the only one
9073 // associated loop) or lastprivate (for simd directives with several
9074 // collapsed or ordered loops).
9075 if (DVar.CKind == OMPC_unknown)
9076 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9077 PrivateRef);
9078 }
9079 }
9080 }
9081 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9082 }
9083}
9084
9085/// Called on a for stmt to check and extract its iteration space
9086/// for further processing (such as collapsing).
9088 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9089 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9090 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9091 Expr *OrderedLoopCountExpr,
9092 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9094 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9095 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9096 // OpenMP [2.9.1, Canonical Loop Form]
9097 // for (init-expr; test-expr; incr-expr) structured-block
9098 // for (range-decl: range-expr) structured-block
9099 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9100 S = CanonLoop->getLoopStmt();
9101 auto *For = dyn_cast_or_null<ForStmt>(S);
9102 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9103 // Ranged for is supported only in OpenMP 5.0.
9104 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9105 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9106 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9107 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9108 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9109 if (TotalNestedLoopCount > 1) {
9110 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9111 SemaRef.Diag(DSA.getConstructLoc(),
9112 diag::note_omp_collapse_ordered_expr)
9113 << 2 << CollapseLoopCountExpr->getSourceRange()
9114 << OrderedLoopCountExpr->getSourceRange();
9115 else if (CollapseLoopCountExpr)
9116 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9117 diag::note_omp_collapse_ordered_expr)
9118 << 0 << CollapseLoopCountExpr->getSourceRange();
9119 else
9120 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9121 diag::note_omp_collapse_ordered_expr)
9122 << 1 << OrderedLoopCountExpr->getSourceRange();
9123 }
9124 return true;
9125 }
9126 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9127 "No loop body.");
9128 // Postpone analysis in dependent contexts for ranged for loops.
9129 if (CXXFor && SemaRef.CurContext->isDependentContext())
9130 return false;
9131
9132 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9133 For ? For->getForLoc() : CXXFor->getForLoc());
9134
9135 // Check init.
9136 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9137 if (ISC.checkAndSetInit(Init))
9138 return true;
9139
9140 bool HasErrors = false;
9141
9142 // Check loop variable's type.
9143 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9144 // OpenMP [2.6, Canonical Loop Form]
9145 // Var is one of the following:
9146 // A variable of signed or unsigned integer type.
9147 // For C++, a variable of a random access iterator type.
9148 // For C, a variable of a pointer type.
9149 QualType VarType = LCDecl->getType().getNonReferenceType();
9150 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9151 !VarType->isPointerType() &&
9152 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9153 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9154 << SemaRef.getLangOpts().CPlusPlus;
9155 HasErrors = true;
9156 }
9157
9158 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9159 // a Construct
9160 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9161 // parallel for construct is (are) private.
9162 // The loop iteration variable in the associated for-loop of a simd
9163 // construct with just one associated for-loop is linear with a
9164 // constant-linear-step that is the increment of the associated for-loop.
9165 // Exclude loop var from the list of variables with implicitly defined data
9166 // sharing attributes.
9167 VarsWithImplicitDSA.erase(LCDecl);
9168
9169 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9170
9171 // Check test-expr.
9172 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9173
9174 // Check incr-expr.
9175 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9176 }
9177
9178 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9179 return HasErrors;
9180
9181 // Build the loop's iteration space representation.
9182 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9183 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9184 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9185 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9191 Captures);
9192 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9193 ISC.buildCounterVar(Captures, DSA);
9194 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9195 ISC.buildPrivateCounterVar();
9196 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9197 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9198 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9199 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9200 ISC.getConditionSrcRange();
9201 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9202 ISC.getIncrementSrcRange();
9203 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9204 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9205 ISC.isStrictTestOp();
9206 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9207 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9208 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9209 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9210 ISC.buildFinalCondition(DSA.getCurScope());
9211 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9212 ISC.doesInitDependOnLC();
9213 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9214 ISC.doesCondDependOnLC();
9215 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9216 ISC.getLoopDependentIdx();
9217
9218 HasErrors |=
9219 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9220 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9221 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9222 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9223 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9224 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9225 if (!HasErrors && DSA.isOrderedRegion()) {
9226 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9227 if (CurrentNestedLoopCount <
9228 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9229 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9230 CurrentNestedLoopCount,
9231 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9232 DSA.getOrderedRegionParam().second->setLoopCounter(
9233 CurrentNestedLoopCount,
9234 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9235 }
9236 }
9237 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9238 if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
9239 // Erroneous case - clause has some problems.
9240 continue;
9241 }
9242 if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
9243 Pair.second.size() <= CurrentNestedLoopCount) {
9244 // Erroneous case - clause has some problems.
9245 Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
9246 continue;
9247 }
9248 Expr *CntValue;
9249 if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
9250 CntValue = ISC.buildOrderedLoopData(
9251 DSA.getCurScope(),
9252 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9253 Pair.first->getDependencyLoc());
9254 else
9255 CntValue = ISC.buildOrderedLoopData(
9256 DSA.getCurScope(),
9257 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9258 Pair.first->getDependencyLoc(),
9259 Pair.second[CurrentNestedLoopCount].first,
9260 Pair.second[CurrentNestedLoopCount].second);
9261 Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
9262 }
9263 }
9264
9265 return HasErrors;
9266}
9267
9268/// Build 'VarRef = Start.
9269static ExprResult
9271 ExprResult Start, bool IsNonRectangularLB,
9272 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9273 // Build 'VarRef = Start.
9274 ExprResult NewStart = IsNonRectangularLB
9275 ? Start.get()
9276 : tryBuildCapture(SemaRef, Start.get(), Captures);
9277 if (!NewStart.isUsable())
9278 return ExprError();
9279 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9280 VarRef.get()->getType())) {
9281 NewStart = SemaRef.PerformImplicitConversion(
9282 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9283 /*AllowExplicit=*/true);
9284 if (!NewStart.isUsable())
9285 return ExprError();
9286 }
9287
9288 ExprResult Init =
9289 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9290 return Init;
9291}
9292
9293/// Build 'VarRef = Start + Iter * Step'.
9295 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9296 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9297 bool IsNonRectangularLB,
9298 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9299 // Add parentheses (for debugging purposes only).
9300 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9301 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9302 !Step.isUsable())
9303 return ExprError();
9304
9305 ExprResult NewStep = Step;
9306 if (Captures)
9307 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9308 if (NewStep.isInvalid())
9309 return ExprError();
9310 ExprResult Update =
9311 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9312 if (!Update.isUsable())
9313 return ExprError();
9314
9315 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9316 // 'VarRef = Start (+|-) Iter * Step'.
9317 if (!Start.isUsable())
9318 return ExprError();
9319 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9320 if (!NewStart.isUsable())
9321 return ExprError();
9322 if (Captures && !IsNonRectangularLB)
9323 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9324 if (NewStart.isInvalid())
9325 return ExprError();
9326
9327 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9328 ExprResult SavedUpdate = Update;
9329 ExprResult UpdateVal;
9330 if (VarRef.get()->getType()->isOverloadableType() ||
9331 NewStart.get()->getType()->isOverloadableType() ||
9332 Update.get()->getType()->isOverloadableType()) {
9333 Sema::TentativeAnalysisScope Trap(SemaRef);
9334
9335 Update =
9336 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9337 if (Update.isUsable()) {
9338 UpdateVal =
9339 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9340 VarRef.get(), SavedUpdate.get());
9341 if (UpdateVal.isUsable()) {
9342 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9343 UpdateVal.get());
9344 }
9345 }
9346 }
9347
9348 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9349 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9350 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9351 NewStart.get(), SavedUpdate.get());
9352 if (!Update.isUsable())
9353 return ExprError();
9354
9355 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9356 VarRef.get()->getType())) {
9357 Update = SemaRef.PerformImplicitConversion(
9358 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9359 if (!Update.isUsable())
9360 return ExprError();
9361 }
9362
9363 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9364 }
9365 return Update;
9366}
9367
9368/// Convert integer expression \a E to make it have at least \a Bits
9369/// bits.
9370static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9371 if (E == nullptr)
9372 return ExprError();
9373 ASTContext &C = SemaRef.Context;
9374 QualType OldType = E->getType();
9375 unsigned HasBits = C.getTypeSize(OldType);
9376 if (HasBits >= Bits)
9377 return ExprResult(E);
9378 // OK to convert to signed, because new type has more bits than old.
9379 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9380 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9381 true);
9382}
9383
9384/// Check if the given expression \a E is a constant integer that fits
9385/// into \a Bits bits.
9386static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9387 if (E == nullptr)
9388 return false;
9390 E->getIntegerConstantExpr(SemaRef.Context))
9391 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9392 return false;
9393}
9394
9395/// Build preinits statement for the given declarations.
9397 MutableArrayRef<Decl *> PreInits) {
9398 if (!PreInits.empty()) {
9399 return new (Context) DeclStmt(
9400 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9402 }
9403 return nullptr;
9404}
9405
9406/// Build preinits statement for the given declarations.
9407static Stmt *
9409 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9410 if (!Captures.empty()) {
9411 SmallVector<Decl *, 16> PreInits;
9412 for (const auto &Pair : Captures)
9413 PreInits.push_back(Pair.second->getDecl());
9414 return buildPreInits(Context, PreInits);
9415 }
9416 return nullptr;
9417}
9418
9419/// Build postupdate expression for the given list of postupdates expressions.
9420static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9421 Expr *PostUpdate = nullptr;
9422 if (!PostUpdates.empty()) {
9423 for (Expr *E : PostUpdates) {
9424 Expr *ConvE = S.BuildCStyleCastExpr(
9425 E->getExprLoc(),
9427 E->getExprLoc(), E)
9428 .get();
9429 PostUpdate = PostUpdate
9430 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9431 PostUpdate, ConvE)
9432 .get()
9433 : ConvE;
9434 }
9435 }
9436 return PostUpdate;
9437}
9438
9439/// Called on a for stmt to check itself and nested loops (if any).
9440/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9441/// number of collapsed loops otherwise.
9442static unsigned
9443checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9444 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9445 DSAStackTy &DSA,
9446 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9447 OMPLoopBasedDirective::HelperExprs &Built) {
9448 unsigned NestedLoopCount = 1;
9449 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9451
9452 if (CollapseLoopCountExpr) {
9453 // Found 'collapse' clause - calculate collapse number.
9455 if (!CollapseLoopCountExpr->isValueDependent() &&
9456 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9457 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9458 } else {
9459 Built.clear(/*Size=*/1);
9460 return 1;
9461 }
9462 }
9463 unsigned OrderedLoopCount = 1;
9464 if (OrderedLoopCountExpr) {
9465 // Found 'ordered' clause - calculate collapse number.
9466 Expr::EvalResult EVResult;
9467 if (!OrderedLoopCountExpr->isValueDependent() &&
9468 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9469 SemaRef.getASTContext())) {
9470 llvm::APSInt Result = EVResult.Val.getInt();
9471 if (Result.getLimitedValue() < NestedLoopCount) {
9472 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9473 diag::err_omp_wrong_ordered_loop_count)
9474 << OrderedLoopCountExpr->getSourceRange();
9475 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9476 diag::note_collapse_loop_count)
9477 << CollapseLoopCountExpr->getSourceRange();
9478 }
9479 OrderedLoopCount = Result.getLimitedValue();
9480 } else {
9481 Built.clear(/*Size=*/1);
9482 return 1;
9483 }
9484 }
9485 // This is helper routine for loop directives (e.g., 'for', 'simd',
9486 // 'for simd', etc.).
9487 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9488 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9489 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9490 if (!OMPLoopBasedDirective::doForAllLoops(
9492 SupportsNonPerfectlyNested, NumLoops,
9493 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9494 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9495 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9497 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9498 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9499 VarsWithImplicitDSA, IterSpaces, Captures))
9500 return true;
9501 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9502 IterSpaces[Cnt].CounterVar) {
9503 // Handle initialization of captured loop iterator variables.
9504 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9505 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9506 Captures[DRE] = DRE;
9507 }
9508 }
9509 return false;
9510 },
9511 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9512 Stmt *DependentPreInits = Transform->getPreInits();
9513 if (!DependentPreInits)
9514 return;
9515 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9516 auto *D = cast<VarDecl>(C);
9517 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9518 Transform->getBeginLoc());
9519 Captures[Ref] = Ref;
9520 }
9521 }))
9522 return 0;
9523
9524 Built.clear(/* size */ NestedLoopCount);
9525
9526 if (SemaRef.CurContext->isDependentContext())
9527 return NestedLoopCount;
9528
9529 // An example of what is generated for the following code:
9530 //
9531 // #pragma omp simd collapse(2) ordered(2)
9532 // for (i = 0; i < NI; ++i)
9533 // for (k = 0; k < NK; ++k)
9534 // for (j = J0; j < NJ; j+=2) {
9535 // <loop body>
9536 // }
9537 //
9538 // We generate the code below.
9539 // Note: the loop body may be outlined in CodeGen.
9540 // Note: some counters may be C++ classes, operator- is used to find number of
9541 // iterations and operator+= to calculate counter value.
9542 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9543 // or i64 is currently supported).
9544 //
9545 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9546 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9547 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9548 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9549 // // similar updates for vars in clauses (e.g. 'linear')
9550 // <loop body (using local i and j)>
9551 // }
9552 // i = NI; // assign final values of counters
9553 // j = NJ;
9554 //
9555
9556 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9557 // the iteration counts of the collapsed for loops.
9558 // Precondition tests if there is at least one iteration (all conditions are
9559 // true).
9560 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9561 Expr *N0 = IterSpaces[0].NumIterations;
9562 ExprResult LastIteration32 =
9563 widenIterationCount(/*Bits=*/32,
9564 SemaRef
9565 .PerformImplicitConversion(
9566 N0->IgnoreImpCasts(), N0->getType(),
9567 Sema::AA_Converting, /*AllowExplicit=*/true)
9568 .get(),
9569 SemaRef);
9570 ExprResult LastIteration64 = widenIterationCount(
9571 /*Bits=*/64,
9572 SemaRef
9573 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9575 /*AllowExplicit=*/true)
9576 .get(),
9577 SemaRef);
9578
9579 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9580 return NestedLoopCount;
9581
9582 ASTContext &C = SemaRef.Context;
9583 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9584
9585 Scope *CurScope = DSA.getCurScope();
9586 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9587 if (PreCond.isUsable()) {
9588 PreCond =
9589 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9590 PreCond.get(), IterSpaces[Cnt].PreCond);
9591 }
9592 Expr *N = IterSpaces[Cnt].NumIterations;
9593 SourceLocation Loc = N->getExprLoc();
9594 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9595 if (LastIteration32.isUsable())
9596 LastIteration32 = SemaRef.BuildBinOp(
9597 CurScope, Loc, BO_Mul, LastIteration32.get(),
9598 SemaRef
9599 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9601 /*AllowExplicit=*/true)
9602 .get());
9603 if (LastIteration64.isUsable())
9604 LastIteration64 = SemaRef.BuildBinOp(
9605 CurScope, Loc, BO_Mul, LastIteration64.get(),
9606 SemaRef
9607 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9609 /*AllowExplicit=*/true)
9610 .get());
9611 }
9612
9613 // Choose either the 32-bit or 64-bit version.
9614 ExprResult LastIteration = LastIteration64;
9615 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9616 (LastIteration32.isUsable() &&
9617 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9618 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9619 fitsInto(
9620 /*Bits=*/32,
9621 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9622 LastIteration64.get(), SemaRef))))
9623 LastIteration = LastIteration32;
9624 QualType VType = LastIteration.get()->getType();
9625 QualType RealVType = VType;
9626 QualType StrideVType = VType;
9627 if (isOpenMPTaskLoopDirective(DKind)) {
9628 VType =
9629 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9630 StrideVType =
9631 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9632 }
9633
9634 if (!LastIteration.isUsable())
9635 return 0;
9636
9637 // Save the number of iterations.
9638 ExprResult NumIterations = LastIteration;
9639 {
9640 LastIteration = SemaRef.BuildBinOp(
9641 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9642 LastIteration.get(),
9643 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9644 if (!LastIteration.isUsable())
9645 return 0;
9646 }
9647
9648 // Calculate the last iteration number beforehand instead of doing this on
9649 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9650 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9651 ExprResult CalcLastIteration;
9652 if (!IsConstant) {
9653 ExprResult SaveRef =
9654 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9655 LastIteration = SaveRef;
9656
9657 // Prepare SaveRef + 1.
9658 NumIterations = SemaRef.BuildBinOp(
9659 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9660 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9661 if (!NumIterations.isUsable())
9662 return 0;
9663 }
9664
9665 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9666
9667 // Build variables passed into runtime, necessary for worksharing directives.
9668 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9673 // Lower bound variable, initialized with zero.
9674 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9675 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9676 SemaRef.AddInitializerToDecl(LBDecl,
9677 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9678 /*DirectInit*/ false);
9679
9680 // Upper bound variable, initialized with last iteration number.
9681 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9682 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9683 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9684 /*DirectInit*/ false);
9685
9686 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9687 // This will be used to implement clause 'lastprivate'.
9688 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9689 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9690 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9691 SemaRef.AddInitializerToDecl(ILDecl,
9692 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9693 /*DirectInit*/ false);
9694
9695 // Stride variable returned by runtime (we initialize it to 1 by default).
9696 VarDecl *STDecl =
9697 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9698 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9699 SemaRef.AddInitializerToDecl(STDecl,
9700 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9701 /*DirectInit*/ false);
9702
9703 // Build expression: UB = min(UB, LastIteration)
9704 // It is necessary for CodeGen of directives with static scheduling.
9705 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9706 UB.get(), LastIteration.get());
9707 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9708 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9709 LastIteration.get(), UB.get());
9710 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9711 CondOp.get());
9712 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9713
9714 // If we have a combined directive that combines 'distribute', 'for' or
9715 // 'simd' we need to be able to access the bounds of the schedule of the
9716 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9717 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9719 // Lower bound variable, initialized with zero.
9720 VarDecl *CombLBDecl =
9721 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9722 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9723 SemaRef.AddInitializerToDecl(
9724 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9725 /*DirectInit*/ false);
9726
9727 // Upper bound variable, initialized with last iteration number.
9728 VarDecl *CombUBDecl =
9729 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9730 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9731 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9732 /*DirectInit*/ false);
9733
9734 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9735 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9736 ExprResult CombCondOp =
9737 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9738 LastIteration.get(), CombUB.get());
9739 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9740 CombCondOp.get());
9741 CombEUB =
9742 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
9743
9744 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9745 // We expect to have at least 2 more parameters than the 'parallel'
9746 // directive does - the lower and upper bounds of the previous schedule.
9747 assert(CD->getNumParams() >= 4 &&
9748 "Unexpected number of parameters in loop combined directive");
9749
9750 // Set the proper type for the bounds given what we learned from the
9751 // enclosed loops.
9752 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9753 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9754
9755 // Previous lower and upper bounds are obtained from the region
9756 // parameters.
9757 PrevLB =
9758 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9759 PrevUB =
9760 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9761 }
9762 }
9763
9764 // Build the iteration variable and its initialization before loop.
9765 ExprResult IV;
9766 ExprResult Init, CombInit;
9767 {
9768 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9769 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9770 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9775 ? LB.get()
9776 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9777 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9778 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
9779
9781 Expr *CombRHS =
9786 ? CombLB.get()
9787 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9788 CombInit =
9789 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9790 CombInit =
9791 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
9792 }
9793 }
9794
9795 bool UseStrictCompare =
9796 RealVType->hasUnsignedIntegerRepresentation() &&
9797 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9798 return LIS.IsStrictCompare;
9799 });
9800 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9801 // unsigned IV)) for worksharing loops.
9802 SourceLocation CondLoc = AStmt->getBeginLoc();
9803 Expr *BoundUB = UB.get();
9804 if (UseStrictCompare) {
9805 BoundUB =
9806 SemaRef
9807 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9808 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9809 .get();
9810 BoundUB =
9811 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
9812 }
9818 ? SemaRef.BuildBinOp(CurScope, CondLoc,
9819 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
9820 BoundUB)
9821 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9822 NumIterations.get());
9823 ExprResult CombDistCond;
9825 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9826 NumIterations.get());
9827 }
9828
9829 ExprResult CombCond;
9831 Expr *BoundCombUB = CombUB.get();
9832 if (UseStrictCompare) {
9833 BoundCombUB =
9834 SemaRef
9835 .BuildBinOp(
9836 CurScope, CondLoc, BO_Add, BoundCombUB,
9837 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9838 .get();
9839 BoundCombUB =
9840 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
9841 .get();
9842 }
9843 CombCond =
9844 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9845 IV.get(), BoundCombUB);
9846 }
9847 // Loop increment (IV = IV + 1)
9848 SourceLocation IncLoc = AStmt->getBeginLoc();
9849 ExprResult Inc =
9850 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
9851 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
9852 if (!Inc.isUsable())
9853 return 0;
9854 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
9855 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
9856 if (!Inc.isUsable())
9857 return 0;
9858
9859 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
9860 // Used for directives with static scheduling.
9861 // In combined construct, add combined version that use CombLB and CombUB
9862 // base variables for the update
9863 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9868 // LB + ST
9869 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
9870 if (!NextLB.isUsable())
9871 return 0;
9872 // LB = LB + ST
9873 NextLB =
9874 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
9875 NextLB =
9876 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
9877 if (!NextLB.isUsable())
9878 return 0;
9879 // UB + ST
9880 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
9881 if (!NextUB.isUsable())
9882 return 0;
9883 // UB = UB + ST
9884 NextUB =
9885 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
9886 NextUB =
9887 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
9888 if (!NextUB.isUsable())
9889 return 0;
9891 CombNextLB =
9892 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
9893 if (!NextLB.isUsable())
9894 return 0;
9895 // LB = LB + ST
9896 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
9897 CombNextLB.get());
9898 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
9899 /*DiscardedValue*/ false);
9900 if (!CombNextLB.isUsable())
9901 return 0;
9902 // UB + ST
9903 CombNextUB =
9904 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
9905 if (!CombNextUB.isUsable())
9906 return 0;
9907 // UB = UB + ST
9908 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
9909 CombNextUB.get());
9910 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
9911 /*DiscardedValue*/ false);
9912 if (!CombNextUB.isUsable())
9913 return 0;
9914 }
9915 }
9916
9917 // Create increment expression for distribute loop when combined in a same
9918 // directive with for as IV = IV + ST; ensure upper bound expression based
9919 // on PrevUB instead of NumIterations - used to implement 'for' when found
9920 // in combination with 'distribute', like in 'distribute parallel for'
9921 SourceLocation DistIncLoc = AStmt->getBeginLoc();
9922 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
9924 DistCond = SemaRef.BuildBinOp(
9925 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
9926 assert(DistCond.isUsable() && "distribute cond expr was not built");
9927
9928 DistInc =
9929 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
9930 assert(DistInc.isUsable() && "distribute inc expr was not built");
9931 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
9932 DistInc.get());
9933 DistInc =
9934 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
9935 assert(DistInc.isUsable() && "distribute inc expr was not built");
9936
9937 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
9938 // construct
9939 ExprResult NewPrevUB = PrevUB;
9940 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
9941 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
9942 PrevUB.get()->getType())) {
9943 NewPrevUB = SemaRef.BuildCStyleCastExpr(
9944 DistEUBLoc,
9946 DistEUBLoc, NewPrevUB.get());
9947 if (!NewPrevUB.isUsable())
9948 return 0;
9949 }
9950 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
9951 UB.get(), NewPrevUB.get());
9952 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9953 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
9954 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
9955 CondOp.get());
9956 PrevEUB =
9957 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
9958
9959 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
9960 // parallel for is in combination with a distribute directive with
9961 // schedule(static, 1)
9962 Expr *BoundPrevUB = PrevUB.get();
9963 if (UseStrictCompare) {
9964 BoundPrevUB =
9965 SemaRef
9966 .BuildBinOp(
9967 CurScope, CondLoc, BO_Add, BoundPrevUB,
9968 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9969 .get();
9970 BoundPrevUB =
9971 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
9972 .get();
9973 }
9974 ParForInDistCond =
9975 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9976 IV.get(), BoundPrevUB);
9977 }
9978
9979 // Build updates and final values of the loop counters.
9980 bool HasErrors = false;
9981 Built.Counters.resize(NestedLoopCount);
9982 Built.Inits.resize(NestedLoopCount);
9983 Built.Updates.resize(NestedLoopCount);
9984 Built.Finals.resize(NestedLoopCount);
9985 Built.DependentCounters.resize(NestedLoopCount);
9986 Built.DependentInits.resize(NestedLoopCount);
9987 Built.FinalsConditions.resize(NestedLoopCount);
9988 {
9989 // We implement the following algorithm for obtaining the
9990 // original loop iteration variable values based on the
9991 // value of the collapsed loop iteration variable IV.
9992 //
9993 // Let n+1 be the number of collapsed loops in the nest.
9994 // Iteration variables (I0, I1, .... In)
9995 // Iteration counts (N0, N1, ... Nn)
9996 //
9997 // Acc = IV;
9998 //
9999 // To compute Ik for loop k, 0 <= k <= n, generate:
10000 // Prod = N(k+1) * N(k+2) * ... * Nn;
10001 // Ik = Acc / Prod;
10002 // Acc -= Ik * Prod;
10003 //
10004 ExprResult Acc = IV;
10005 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10006 LoopIterationSpace &IS = IterSpaces[Cnt];
10007 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10008 ExprResult Iter;
10009
10010 // Compute prod
10011 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10012 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10013 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10014 IterSpaces[K].NumIterations);
10015
10016 // Iter = Acc / Prod
10017 // If there is at least one more inner loop to avoid
10018 // multiplication by 1.
10019 if (Cnt + 1 < NestedLoopCount)
10020 Iter =
10021 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10022 else
10023 Iter = Acc;
10024 if (!Iter.isUsable()) {
10025 HasErrors = true;
10026 break;
10027 }
10028
10029 // Update Acc:
10030 // Acc -= Iter * Prod
10031 // Check if there is at least one more inner loop to avoid
10032 // multiplication by 1.
10033 if (Cnt + 1 < NestedLoopCount)
10034 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10035 Prod.get());
10036 else
10037 Prod = Iter;
10038 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10039
10040 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10041 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10042 DeclRefExpr *CounterVar = buildDeclRefExpr(
10043 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10044 /*RefersToCapture=*/true);
10045 ExprResult Init =
10046 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10047 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10048 if (!Init.isUsable()) {
10049 HasErrors = true;
10050 break;
10051 }
10053 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10054 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10055 if (!Update.isUsable()) {
10056 HasErrors = true;
10057 break;
10058 }
10059
10060 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10061 ExprResult Final =
10062 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10063 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10064 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10065 if (!Final.isUsable()) {
10066 HasErrors = true;
10067 break;
10068 }
10069
10070 if (!Update.isUsable() || !Final.isUsable()) {
10071 HasErrors = true;
10072 break;
10073 }
10074 // Save results
10075 Built.Counters[Cnt] = IS.CounterVar;
10076 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10077 Built.Inits[Cnt] = Init.get();
10078 Built.Updates[Cnt] = Update.get();
10079 Built.Finals[Cnt] = Final.get();
10080 Built.DependentCounters[Cnt] = nullptr;
10081 Built.DependentInits[Cnt] = nullptr;
10082 Built.FinalsConditions[Cnt] = nullptr;
10083 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10084 Built.DependentCounters[Cnt] =
10085 Built.Counters[NestedLoopCount - 1 - IS.LoopDependentIdx];
10086 Built.DependentInits[Cnt] =
10087 Built.Inits[NestedLoopCount - 1 - IS.LoopDependentIdx];
10088 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10089 }
10090 }
10091 }
10092
10093 if (HasErrors)
10094 return 0;
10095
10096 // Save results
10097 Built.IterationVarRef = IV.get();
10098 Built.LastIteration = LastIteration.get();
10099 Built.NumIterations = NumIterations.get();
10100 Built.CalcLastIteration = SemaRef
10101 .ActOnFinishFullExpr(CalcLastIteration.get(),
10102 /*DiscardedValue=*/false)
10103 .get();
10104 Built.PreCond = PreCond.get();
10105 Built.PreInits = buildPreInits(C, Captures);
10106 Built.Cond = Cond.get();
10107 Built.Init = Init.get();
10108 Built.Inc = Inc.get();
10109 Built.LB = LB.get();
10110 Built.UB = UB.get();
10111 Built.IL = IL.get();
10112 Built.ST = ST.get();
10113 Built.EUB = EUB.get();
10114 Built.NLB = NextLB.get();
10115 Built.NUB = NextUB.get();
10116 Built.PrevLB = PrevLB.get();
10117 Built.PrevUB = PrevUB.get();
10118 Built.DistInc = DistInc.get();
10119 Built.PrevEUB = PrevEUB.get();
10120 Built.DistCombinedFields.LB = CombLB.get();
10121 Built.DistCombinedFields.UB = CombUB.get();
10122 Built.DistCombinedFields.EUB = CombEUB.get();
10123 Built.DistCombinedFields.Init = CombInit.get();
10124 Built.DistCombinedFields.Cond = CombCond.get();
10125 Built.DistCombinedFields.NLB = CombNextLB.get();
10126 Built.DistCombinedFields.NUB = CombNextUB.get();
10127 Built.DistCombinedFields.DistCond = CombDistCond.get();
10128 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10129
10130 return NestedLoopCount;
10131}
10132
10134 auto CollapseClauses =
10135 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10136 if (CollapseClauses.begin() != CollapseClauses.end())
10137 return (*CollapseClauses.begin())->getNumForLoops();
10138 return nullptr;
10139}
10140
10142 auto OrderedClauses =
10143 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10144 if (OrderedClauses.begin() != OrderedClauses.end())
10145 return (*OrderedClauses.begin())->getNumForLoops();
10146 return nullptr;
10147}
10148
10150 const ArrayRef<OMPClause *> Clauses) {
10151 const OMPSafelenClause *Safelen = nullptr;
10152 const OMPSimdlenClause *Simdlen = nullptr;
10153
10154 for (const OMPClause *Clause : Clauses) {
10155 if (Clause->getClauseKind() == OMPC_safelen)
10156 Safelen = cast<OMPSafelenClause>(Clause);
10157 else if (Clause->getClauseKind() == OMPC_simdlen)
10158 Simdlen = cast<OMPSimdlenClause>(Clause);
10159 if (Safelen && Simdlen)
10160 break;
10161 }
10162
10163 if (Simdlen && Safelen) {
10164 const Expr *SimdlenLength = Simdlen->getSimdlen();
10165 const Expr *SafelenLength = Safelen->getSafelen();
10166 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10167 SimdlenLength->isInstantiationDependent() ||
10168 SimdlenLength->containsUnexpandedParameterPack())
10169 return false;
10170 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10171 SafelenLength->isInstantiationDependent() ||
10172 SafelenLength->containsUnexpandedParameterPack())
10173 return false;
10174 Expr::EvalResult SimdlenResult, SafelenResult;
10175 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10176 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10177 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10178 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10179 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10180 // If both simdlen and safelen clauses are specified, the value of the
10181 // simdlen parameter must be less than or equal to the value of the safelen
10182 // parameter.
10183 if (SimdlenRes > SafelenRes) {
10184 S.Diag(SimdlenLength->getExprLoc(),
10185 diag::err_omp_wrong_simdlen_safelen_values)
10186 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10187 return true;
10188 }
10189 }
10190 return false;
10191}
10192
10193StmtResult
10195 SourceLocation StartLoc, SourceLocation EndLoc,
10196 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10197 if (!AStmt)
10198 return StmtError();
10199
10200 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10201 OMPLoopBasedDirective::HelperExprs B;
10202 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10203 // define the nested loops number.
10204 unsigned NestedLoopCount = checkOpenMPLoop(
10205 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10206 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10207 if (NestedLoopCount == 0)
10208 return StmtError();
10209
10210 assert((CurContext->isDependentContext() || B.builtAll()) &&
10211 "omp simd loop exprs were not built");
10212
10214 // Finalize the clauses that need pre-built expressions for CodeGen.
10215 for (OMPClause *C : Clauses) {
10216 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10217 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10218 B.NumIterations, *this, CurScope,
10219 DSAStack))
10220 return StmtError();
10221 }
10222 }
10223
10224 if (checkSimdlenSafelenSpecified(*this, Clauses))
10225 return StmtError();
10226
10228 return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10229 Clauses, AStmt, B);
10230}
10231
10234 SourceLocation StartLoc, SourceLocation EndLoc,
10235 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10236 if (!AStmt)
10237 return StmtError();
10238
10239 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10240 OMPLoopBasedDirective::HelperExprs B;
10241 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10242 // define the nested loops number.
10243 unsigned NestedLoopCount = checkOpenMPLoop(
10244 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10245 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10246 if (NestedLoopCount == 0)
10247 return StmtError();
10248
10249 assert((CurContext->isDependentContext() || B.builtAll()) &&
10250 "omp for loop exprs were not built");
10251
10253 // Finalize the clauses that need pre-built expressions for CodeGen.
10254 for (OMPClause *C : Clauses) {
10255 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10256 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10257 B.NumIterations, *this, CurScope,
10258 DSAStack))
10259 return StmtError();
10260 }
10261 }
10262
10264 return OMPForDirective::Create(
10265 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10266 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10267}
10268
10270 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10271 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10272 if (!AStmt)
10273 return StmtError();
10274
10275 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10276 OMPLoopBasedDirective::HelperExprs B;
10277 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10278 // define the nested loops number.
10279 unsigned NestedLoopCount =
10280 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10281 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10282 VarsWithImplicitDSA, B);
10283 if (NestedLoopCount == 0)
10284 return StmtError();
10285
10286 assert((CurContext->isDependentContext() || B.builtAll()) &&
10287 "omp for simd loop exprs were not built");
10288
10290 // Finalize the clauses that need pre-built expressions for CodeGen.
10291 for (OMPClause *C : Clauses) {
10292 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10293 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10294 B.NumIterations, *this, CurScope,
10295 DSAStack))
10296 return StmtError();
10297 }
10298 }
10299
10300 if (checkSimdlenSafelenSpecified(*this, Clauses))
10301 return StmtError();
10302
10304 return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10305 Clauses, AStmt, B);
10306}
10307
10309 Stmt *AStmt,
10310 SourceLocation StartLoc,
10311 SourceLocation EndLoc) {
10312 if (!AStmt)
10313 return StmtError();
10314
10315 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10316 auto BaseStmt = AStmt;
10317 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10318 BaseStmt = CS->getCapturedStmt();
10319 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10320 auto S = C->children();
10321 if (S.begin() == S.end())
10322 return StmtError();
10323 // All associated statements must be '#pragma omp section' except for
10324 // the first one.
10325 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10326 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10327 if (SectionStmt)
10328 Diag(SectionStmt->getBeginLoc(),
10329 diag::err_omp_sections_substmt_not_section);
10330 return StmtError();
10331 }
10332 cast<OMPSectionDirective>(SectionStmt)
10333 ->setHasCancel(DSAStack->isCancelRegion());
10334 }
10335 } else {
10336 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10337 return StmtError();
10338 }
10339
10341
10342 return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10343 DSAStack->getTaskgroupReductionRef(),
10344 DSAStack->isCancelRegion());
10345}
10346
10348 SourceLocation StartLoc,
10349 SourceLocation EndLoc) {
10350 if (!AStmt)
10351 return StmtError();
10352
10354 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10355
10356 return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
10357 DSAStack->isCancelRegion());
10358}
10359
10361 E = E->IgnoreParenCasts()->IgnoreImplicit();
10362 if (auto *CE = dyn_cast<CallExpr>(E))
10363 if (CE->getDirectCallee())
10364 return E;
10365 return nullptr;
10366}
10367
10369 Stmt *AStmt,
10370 SourceLocation StartLoc,
10371 SourceLocation EndLoc) {
10372 if (!AStmt)
10373 return StmtError();
10374
10375 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10376
10377 // 5.1 OpenMP
10378 // expression-stmt : an expression statement with one of the following forms:
10379 // expression = target-call ( [expression-list] );
10380 // target-call ( [expression-list] );
10381
10382 SourceLocation TargetCallLoc;
10383
10385 Expr *TargetCall = nullptr;
10386
10387 auto *E = dyn_cast<Expr>(S);
10388 if (!E) {
10389 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10390 return StmtError();
10391 }
10392
10393 E = E->IgnoreParenCasts()->IgnoreImplicit();
10394
10395 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10396 if (BO->getOpcode() == BO_Assign)
10397 TargetCall = getDirectCallExpr(BO->getRHS());
10398 } else {
10399 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10400 if (COCE->getOperator() == OO_Equal)
10401 TargetCall = getDirectCallExpr(COCE->getArg(1));
10402 if (!TargetCall)
10403 TargetCall = getDirectCallExpr(E);
10404 }
10405 if (!TargetCall) {
10406 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10407 return StmtError();
10408 }
10409 TargetCallLoc = TargetCall->getExprLoc();
10410 }
10411
10413
10414 return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10415 TargetCallLoc);
10416}
10417
10420 DSAStackTy *Stack) {
10421 bool ErrorFound = false;
10422 for (OMPClause *C : Clauses) {
10423 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10424 for (Expr *RefExpr : LPC->varlists()) {
10425 SourceLocation ELoc;
10426 SourceRange ERange;
10427 Expr *SimpleRefExpr = RefExpr;
10428 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10429 if (ValueDecl *D = Res.first) {
10430 auto &&Info = Stack->isLoopControlVariable(D);
10431 if (!Info.first) {
10432 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10433 << getOpenMPDirectiveName(K);
10434 ErrorFound = true;
10435 }
10436 }
10437 }
10438 }
10439 }
10440 return ErrorFound;
10441}
10442
10444 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10445 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10446 if (!AStmt)
10447 return StmtError();
10448
10449 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10450 // A list item may not appear in a lastprivate clause unless it is the
10451 // loop iteration variable of a loop that is associated with the construct.
10452 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack))
10453 return StmtError();
10454
10455 auto *CS = cast<CapturedStmt>(AStmt);
10456 // 1.2.2 OpenMP Language Terminology
10457 // Structured block - An executable statement with a single entry at the
10458 // top and a single exit at the bottom.
10459 // The point of exit cannot be a branch out of the structured block.
10460 // longjmp() and throw() must not violate the entry/exit criteria.
10461 CS->getCapturedDecl()->setNothrow();
10462
10463 OMPLoopDirective::HelperExprs B;
10464 // In presence of clause 'collapse', it will define the nested loops number.
10465 unsigned NestedLoopCount = checkOpenMPLoop(
10466 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10467 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10468 if (NestedLoopCount == 0)
10469 return StmtError();
10470
10471 assert((CurContext->isDependentContext() || B.builtAll()) &&
10472 "omp loop exprs were not built");
10473
10475 return OMPGenericLoopDirective::Create(Context, StartLoc, EndLoc,
10476 NestedLoopCount, Clauses, AStmt, B);
10477}
10478
10480 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10481 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10482 if (!AStmt)
10483 return StmtError();
10484
10485 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10486 // A list item may not appear in a lastprivate clause unless it is the
10487 // loop iteration variable of a loop that is associated with the construct.
10488 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStack))
10489 return StmtError();
10490
10491 auto *CS = cast<CapturedStmt>(AStmt);
10492 // 1.2.2 OpenMP Language Terminology
10493 // Structured block - An executable statement with a single entry at the
10494 // top and a single exit at the bottom.
10495 // The point of exit cannot be a branch out of the structured block.
10496 // longjmp() and throw() must not violate the entry/exit criteria.
10497 CS->getCapturedDecl()->setNothrow();
10498 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10499 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10501 // 1.2.2 OpenMP Language Terminology
10502 // Structured block - An executable statement with a single entry at the
10503 // top and a single exit at the bottom.
10504 // The point of exit cannot be a branch out of the structured block.
10505 // longjmp() and throw() must not violate the entry/exit criteria.
10506 CS->getCapturedDecl()->setNothrow();
10507 }
10508
10509 OMPLoopDirective::HelperExprs B;
10510 // In presence of clause 'collapse', it will define the nested loops number.
10511 unsigned NestedLoopCount =
10512 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10513 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10514 VarsWithImplicitDSA, B);
10515 if (NestedLoopCount == 0)
10516 return StmtError();
10517
10518 assert((CurContext->isDependentContext() || B.builtAll()) &&
10519 "omp loop exprs were not built");
10520
10522 DSAStack->setParentTeamsRegionLoc(StartLoc);
10523
10525 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10526}
10527
10529 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10530 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10531 if (!AStmt)
10532 return StmtError();
10533
10534 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10535 // A list item may not appear in a lastprivate clause unless it is the
10536 // loop iteration variable of a loop that is associated with the construct.
10537 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10538 DSAStack))
10539 return StmtError();
10540
10541 auto *CS = cast<CapturedStmt>(AStmt);
10542 // 1.2.2 OpenMP Language Terminology
10543 // Structured block - An executable statement with a single entry at the
10544 // top and a single exit at the bottom.
10545 // The point of exit cannot be a branch out of the structured block.
10546 // longjmp() and throw() must not violate the entry/exit criteria.
10547 CS->getCapturedDecl()->setNothrow();
10548 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10549 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10551 // 1.2.2 OpenMP Language Terminology
10552 // Structured block - An executable statement with a single entry at the
10553 // top and a single exit at the bottom.
10554 // The point of exit cannot be a branch out of the structured block.
10555 // longjmp() and throw() must not violate the entry/exit criteria.
10556 CS->getCapturedDecl()->setNothrow();
10557 }
10558
10559 OMPLoopDirective::HelperExprs B;
10560 // In presence of clause 'collapse', it will define the nested loops number.
10561 unsigned NestedLoopCount =
10562 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10563 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10564 VarsWithImplicitDSA, B);
10565 if (NestedLoopCount == 0)
10566 return StmtError();
10567
10568 assert((CurContext->isDependentContext() || B.builtAll()) &&
10569 "omp loop exprs were not built");
10570
10572
10574 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10575}
10576
10578 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10579 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10580 if (!AStmt)
10581 return StmtError();
10582
10583 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10584 // A list item may not appear in a lastprivate clause unless it is the
10585 // loop iteration variable of a loop that is associated with the construct.
10586 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStack))
10587 return StmtError();
10588
10589 auto *CS = cast<CapturedStmt>(AStmt);
10590 // 1.2.2 OpenMP Language Terminology
10591 // Structured block - An executable statement with a single entry at the
10592 // top and a single exit at the bottom.
10593 // The point of exit cannot be a branch out of the structured block.
10594 // longjmp() and throw() must not violate the entry/exit criteria.
10595 CS->getCapturedDecl()->setNothrow();
10596 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10597 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10599 // 1.2.2 OpenMP Language Terminology
10600 // Structured block - An executable statement with a single entry at the
10601 // top and a single exit at the bottom.
10602 // The point of exit cannot be a branch out of the structured block.
10603 // longjmp() and throw() must not violate the entry/exit criteria.
10604 CS->getCapturedDecl()->setNothrow();
10605 }
10606
10607 OMPLoopDirective::HelperExprs B;
10608 // In presence of clause 'collapse', it will define the nested loops number.
10609 unsigned NestedLoopCount =
10610 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10611 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10612 VarsWithImplicitDSA, B);
10613 if (NestedLoopCount == 0)
10614 return StmtError();
10615
10616 assert((CurContext->isDependentContext() || B.builtAll()) &&
10617 "omp loop exprs were not built");
10618
10620
10622 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10623}
10624
10626 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10627 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10628 if (!AStmt)
10629 return StmtError();
10630
10631 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10632 // A list item may not appear in a lastprivate clause unless it is the
10633 // loop iteration variable of a loop that is associated with the construct.
10634 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10635 DSAStack))
10636 return StmtError();
10637
10638 auto *CS = cast<CapturedStmt>(AStmt);
10639 // 1.2.2 OpenMP Language Terminology
10640 // Structured block - An executable statement with a single entry at the
10641 // top and a single exit at the bottom.
10642 // The point of exit cannot be a branch out of the structured block.
10643 // longjmp() and throw() must not violate the entry/exit criteria.
10644 CS->getCapturedDecl()->setNothrow();
10645 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10646 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10648 // 1.2.2 OpenMP Language Terminology
10649 // Structured block - An executable statement with a single entry at the
10650 // top and a single exit at the bottom.
10651 // The point of exit cannot be a branch out of the structured block.
10652 // longjmp() and throw() must not violate the entry/exit criteria.
10653 CS->getCapturedDecl()->setNothrow();
10654 }
10655
10656 OMPLoopDirective::HelperExprs B;
10657 // In presence of clause 'collapse', it will define the nested loops number.
10658 unsigned NestedLoopCount =
10659 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10660 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10661 VarsWithImplicitDSA, B);
10662 if (NestedLoopCount == 0)
10663 return StmtError();
10664
10665 assert((CurContext->isDependentContext() || B.builtAll()) &&
10666 "omp loop exprs were not built");
10667
10669
10671 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10672}
10673
10675 Stmt *AStmt,
10676 SourceLocation StartLoc,
10677 SourceLocation EndLoc) {
10678 if (!AStmt)
10679 return StmtError();
10680
10681 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10682
10684
10685 // OpenMP [2.7.3, single Construct, Restrictions]
10686 // The copyprivate clause must not be used with the nowait clause.
10687 const OMPClause *Nowait = nullptr;
10688 const OMPClause *Copyprivate = nullptr;
10689 for (const OMPClause *Clause : Clauses) {
10690 if (Clause->getClauseKind() == OMPC_nowait)
10691 Nowait = Clause;
10692 else if (Clause->getClauseKind() == OMPC_copyprivate)
10693 Copyprivate = Clause;
10694 if (Copyprivate && Nowait) {
10695 Diag(Copyprivate->getBeginLoc(),
10696 diag::err_omp_single_copyprivate_with_nowait);
10697 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10698 return StmtError();
10699 }
10700 }
10701
10702 return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10703}
10704
10706 SourceLocation StartLoc,
10707 SourceLocation EndLoc) {
10708 if (!AStmt)
10709 return StmtError();
10710
10712
10713 return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
10714}
10715
10717 Stmt *AStmt,
10718 SourceLocation StartLoc,
10719 SourceLocation EndLoc) {
10720 if (!AStmt)
10721 return StmtError();
10722
10724
10725 return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10726}
10727
10729 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10730 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10731 if (!AStmt)
10732 return StmtError();
10733
10734 bool ErrorFound = false;
10735 llvm::APSInt Hint;
10736 SourceLocation HintLoc;
10737 bool DependentHint = false;
10738 for (const OMPClause *C : Clauses) {
10739 if (C->getClauseKind() == OMPC_hint) {
10740 if (!DirName.getName()) {
10741 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10742 ErrorFound = true;
10743 }
10744 Expr *E = cast<OMPHintClause>(C)->getHint();
10745 if (E->isTypeDependent() || E->isValueDependent() ||
10747 DependentHint = true;
10748 } else {
10749 Hint = E->EvaluateKnownConstInt(Context);
10750 HintLoc = C->getBeginLoc();
10751 }
10752 }
10753 }
10754 if (ErrorFound)
10755 return StmtError();
10756 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10757 if (Pair.first && DirName.getName() && !DependentHint) {
10758 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10759 Diag(StartLoc, diag::err_omp_critical_with_hint);
10760 if (HintLoc.isValid())
10761 Diag(HintLoc, diag::note_omp_critical_hint_here)
10762 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10763 else
10764 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10765 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10766 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10767 << 1
10768 << toString(C->getHint()->EvaluateKnownConstInt(Context),
10769 /*Radix=*/10, /*Signed=*/false);
10770 } else {
10771 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10772 }
10773 }
10774 }
10775
10777
10778 auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
10779 Clauses, AStmt);
10780 if (!Pair.first && DirName.getName() && !DependentHint)
10781 DSAStack->addCriticalWithHint(Dir, Hint);
10782 return Dir;
10783}
10784
10786 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10787 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10788 if (!AStmt)
10789 return StmtError();
10790
10791 auto *CS = cast<CapturedStmt>(AStmt);
10792 // 1.2.2 OpenMP Language Terminology
10793 // Structured block - An executable statement with a single entry at the
10794 // top and a single exit at the bottom.
10795 // The point of exit cannot be a branch out of the structured block.
10796 // longjmp() and throw() must not violate the entry/exit criteria.
10797 CS->getCapturedDecl()->setNothrow();
10798
10799 OMPLoopBasedDirective::HelperExprs B;
10800 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10801 // define the nested loops number.
10802 unsigned NestedLoopCount =
10803 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10804 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10805 VarsWithImplicitDSA, B);
10806 if (NestedLoopCount == 0)
10807 return StmtError();
10808
10809 assert((CurContext->isDependentContext() || B.builtAll()) &&
10810 "omp parallel for loop exprs were not built");
10811
10813 // Finalize the clauses that need pre-built expressions for CodeGen.
10814 for (OMPClause *C : Clauses) {
10815 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10816 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10817 B.NumIterations, *this, CurScope,
10818 DSAStack))
10819 return StmtError();
10820 }
10821 }
10822
10824 return OMPParallelForDirective::Create(
10825 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10826 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10827}
10828
10830 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10831 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10832 if (!AStmt)
10833 return StmtError();
10834
10835 auto *CS = cast<CapturedStmt>(AStmt);
10836 // 1.2.2 OpenMP Language Terminology
10837 // Structured block - An executable statement with a single entry at the
10838 // top and a single exit at the bottom.
10839 // The point of exit cannot be a branch out of the structured block.
10840 // longjmp() and throw() must not violate the entry/exit criteria.
10841 CS->getCapturedDecl()->setNothrow();
10842
10843 OMPLoopBasedDirective::HelperExprs B;
10844 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10845 // define the nested loops number.
10846 unsigned NestedLoopCount =
10847 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10848 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10849 VarsWithImplicitDSA, B);
10850 if (NestedLoopCount == 0)
10851 return StmtError();
10852
10854 // Finalize the clauses that need pre-built expressions for CodeGen.
10855 for (OMPClause *C : Clauses) {
10856 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10857 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10858 B.NumIterations, *this, CurScope,
10859 DSAStack))
10860 return StmtError();
10861 }
10862 }
10863
10864 if (checkSimdlenSafelenSpecified(*this, Clauses))
10865 return StmtError();
10866
10868 return OMPParallelForSimdDirective::Create(
10869 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10870}
10871
10874 Stmt *AStmt, SourceLocation StartLoc,
10875 SourceLocation EndLoc) {
10876 if (!AStmt)
10877 return StmtError();
10878
10879 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10880 auto *CS = cast<CapturedStmt>(AStmt);
10881 // 1.2.2 OpenMP Language Terminology
10882 // Structured block - An executable statement with a single entry at the
10883 // top and a single exit at the bottom.
10884 // The point of exit cannot be a branch out of the structured block.
10885 // longjmp() and throw() must not violate the entry/exit criteria.
10886 CS->getCapturedDecl()->setNothrow();
10887
10889
10890 return OMPParallelMasterDirective::Create(
10891 Context, StartLoc, EndLoc, Clauses, AStmt,
10892 DSAStack->getTaskgroupReductionRef());
10893}
10894
10897 Stmt *AStmt, SourceLocation StartLoc,
10898 SourceLocation EndLoc) {
10899 if (!AStmt)
10900 return StmtError();
10901
10902 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10903 auto *CS = cast<CapturedStmt>(AStmt);
10904 // 1.2.2 OpenMP Language Terminology
10905 // Structured block - An executable statement with a single entry at the
10906 // top and a single exit at the bottom.
10907 // The point of exit cannot be a branch out of the structured block.
10908 // longjmp() and throw() must not violate the entry/exit criteria.
10909 CS->getCapturedDecl()->setNothrow();
10910
10912
10913 return OMPParallelMaskedDirective::Create(
10914 Context, StartLoc, EndLoc, Clauses, AStmt,
10915 DSAStack->getTaskgroupReductionRef());
10916}
10917
10920 Stmt *AStmt, SourceLocation StartLoc,
10921 SourceLocation EndLoc) {
10922 if (!AStmt)
10923 return StmtError();
10924
10925 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10926 auto BaseStmt = AStmt;
10927 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10928 BaseStmt = CS->getCapturedStmt();
10929 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10930 auto S = C->children();
10931 if (S.begin() == S.end())
10932 return StmtError();
10933 // All associated statements must be '#pragma omp section' except for
10934 // the first one.
10935 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10936 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10937 if (SectionStmt)
10938 Diag(SectionStmt->getBeginLoc(),
10939 diag::err_omp_parallel_sections_substmt_not_section);
10940 return StmtError();
10941 }
10942 cast<OMPSectionDirective>(SectionStmt)
10943 ->setHasCancel(DSAStack->isCancelRegion());
10944 }
10945 } else {
10946 Diag(AStmt->getBeginLoc(),
10947 diag::err_omp_parallel_sections_not_compound_stmt);
10948 return StmtError();
10949 }
10950
10952
10953 return OMPParallelSectionsDirective::Create(
10954 Context, StartLoc, EndLoc, Clauses, AStmt,
10955 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10956}
10957
10958/// Find and diagnose mutually exclusive clause kinds.
10960 Sema &S, ArrayRef<OMPClause *> Clauses,
10961 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10962 const OMPClause *PrevClause = nullptr;
10963 bool ErrorFound = false;
10964 for (const OMPClause *C : Clauses) {
10965 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10966 if (!PrevClause) {
10967 PrevClause = C;
10968 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10969 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10970 << getOpenMPClauseName(C->getClauseKind())
10971 << getOpenMPClauseName(PrevClause->getClauseKind());
10972 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10973 << getOpenMPClauseName(PrevClause->getClauseKind());
10974 ErrorFound = true;
10975 }
10976 }
10977 }
10978 return ErrorFound;
10979}
10980
10982 Stmt *AStmt, SourceLocation StartLoc,
10983 SourceLocation EndLoc) {
10984 if (!AStmt)
10985 return StmtError();
10986
10987 // OpenMP 5.0, 2.10.1 task Construct
10988 // If a detach clause appears on the directive, then a mergeable clause cannot
10989 // appear on the same directive.
10990 if (checkMutuallyExclusiveClauses(*this, Clauses,
10991 {OMPC_detach, OMPC_mergeable}))
10992 return StmtError();
10993
10994 auto *CS = cast<CapturedStmt>(AStmt);
10995 // 1.2.2 OpenMP Language Terminology
10996 // Structured block - An executable statement with a single entry at the
10997 // top and a single exit at the bottom.
10998 // The point of exit cannot be a branch out of the structured block.
10999 // longjmp() and throw() must not violate the entry/exit criteria.
11000 CS->getCapturedDecl()->setNothrow();
11001
11003
11004 return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
11005 DSAStack->isCancelRegion());
11006}
11007
11009 SourceLocation EndLoc) {
11010 return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
11011}
11012
11014 SourceLocation EndLoc) {
11015 return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
11016}
11017
11019 SourceLocation StartLoc,
11020 SourceLocation EndLoc) {
11021 return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
11022}
11023
11025 Stmt *AStmt,
11026 SourceLocation StartLoc,
11027 SourceLocation EndLoc) {
11028 if (!AStmt)
11029 return StmtError();
11030
11031 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11032
11034
11035 return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
11036 AStmt,
11037 DSAStack->getTaskgroupReductionRef());
11038}
11039
11041 SourceLocation StartLoc,
11042 SourceLocation EndLoc) {
11043 OMPFlushClause *FC = nullptr;
11044 OMPClause *OrderClause = nullptr;
11045 for (OMPClause *C : Clauses) {
11046 if (C->getClauseKind() == OMPC_flush)
11047 FC = cast<OMPFlushClause>(C);
11048 else
11049 OrderClause = C;
11050 }
11051 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11052 SourceLocation MemOrderLoc;
11053 for (const OMPClause *C : Clauses) {
11054 if (C->getClauseKind() == OMPC_acq_rel ||
11055 C->getClauseKind() == OMPC_acquire ||
11056 C->getClauseKind() == OMPC_release) {
11057 if (MemOrderKind != OMPC_unknown) {
11058 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11059 << getOpenMPDirectiveName(OMPD_flush) << 1
11060 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11061 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11062 << getOpenMPClauseName(MemOrderKind);
11063 } else {
11064 MemOrderKind = C->getClauseKind();
11065 MemOrderLoc = C->getBeginLoc();
11066 }
11067 }
11068 }
11069 if (FC && OrderClause) {
11070 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11071 << getOpenMPClauseName(OrderClause->getClauseKind());
11072 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11073 << getOpenMPClauseName(OrderClause->getClauseKind());
11074 return StmtError();
11075 }
11076 return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
11077}
11078
11080 SourceLocation StartLoc,
11081 SourceLocation EndLoc) {
11082 if (Clauses.empty()) {
11083 Diag(StartLoc, diag::err_omp_depobj_expected);
11084 return StmtError();
11085 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11086 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11087 return StmtError();
11088 }
11089 // Only depobj expression and another single clause is allowed.
11090 if (Clauses.size() > 2) {
11091 Diag(Clauses[2]->getBeginLoc(),
11092 diag::err_omp_depobj_single_clause_expected);
11093 return StmtError();
11094 } else if (Clauses.size() < 1) {
11095 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11096 return StmtError();
11097 }
11098 return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
11099}
11100
11102 SourceLocation StartLoc,
11103 SourceLocation EndLoc) {
11104 // Check that exactly one clause is specified.
11105 if (Clauses.size() != 1) {
11106 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11107 diag::err_omp_scan_single_clause_expected);
11108 return StmtError();
11109 }
11110 // Check that scan directive is used in the scopeof the OpenMP loop body.
11111 if (Scope *S = DSAStack->getCurScope()) {
11112 Scope *ParentS = S->getParent();
11113 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11114 !ParentS->getBreakParent()->isOpenMPLoopScope())
11115 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11116 << getOpenMPDirectiveName(OMPD_scan) << 5);
11117 }
11118 // Check that only one instance of scan directives is used in the same outer
11119 // region.
11120 if (DSAStack->doesParentHasScanDirective()) {
11121 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11122 Diag(DSAStack->getParentScanDirectiveLoc(),
11123 diag::note_omp_previous_directive)
11124 << "scan";
11125 return StmtError();
11126 }
11127 DSAStack->setParentHasScanDirective(StartLoc);
11128 return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
11129}
11130
11132 Stmt *AStmt,
11133 SourceLocation StartLoc,
11134 SourceLocation EndLoc) {
11135 const OMPClause *DependFound = nullptr;
11136 const OMPClause *DependSourceClause = nullptr;
11137 const OMPClause *DependSinkClause = nullptr;
11138 bool ErrorFound = false;
11139 const OMPThreadsClause *TC = nullptr;
11140 const OMPSIMDClause *SC = nullptr;
11141 for (const OMPClause *C : Clauses) {
11142 if (auto *DC = dyn_cast<OMPDependClause>(C)) {
11143 DependFound = C;
11144 if (DC->getDependencyKind() == OMPC_DEPEND_source) {
11145 if (DependSourceClause) {
11146 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11147 << getOpenMPDirectiveName(OMPD_ordered)
11148 << getOpenMPClauseName(OMPC_depend) << 2;
11149 ErrorFound = true;
11150 } else {
11151 DependSourceClause = C;
11152 }
11153 if (DependSinkClause) {
11154 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11155 << 0;
11156 ErrorFound = true;
11157 }
11158 } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
11159 if (DependSourceClause) {
11160 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11161 << 1;
11162 ErrorFound = true;
11163 }
11164 DependSinkClause = C;
11165 }
11166 } else if (C->getClauseKind() == OMPC_threads) {
11168 } else if (C->getClauseKind() == OMPC_simd) {
11169 SC = cast<OMPSIMDClause>(C);
11170 }
11171 }
11172 if (!ErrorFound && !SC &&
11173 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11174 // OpenMP [2.8.1,simd Construct, Restrictions]
11175 // An ordered construct with the simd clause is the only OpenMP construct
11176 // that can appear in the simd region.
11177 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11178 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11179 ErrorFound = true;
11180 } else if (DependFound && (TC || SC)) {
11181 Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd)
11182 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11183 ErrorFound = true;
11184 } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) {
11185 Diag(DependFound->getBeginLoc(),
11186 diag::err_omp_ordered_directive_without_param);
11187 ErrorFound = true;
11188 } else if (TC || Clauses.empty()) {
11189 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11190 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11191 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11192 << (TC != nullptr);
11193 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11194 ErrorFound = true;
11195 }
11196 }
11197 if ((!AStmt && !DependFound) || ErrorFound)
11198 return StmtError();
11199
11200 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11201 // During execution of an iteration of a worksharing-loop or a loop nest
11202 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11203 // must not execute more than one ordered region corresponding to an ordered
11204 // construct without a depend clause.
11205 if (!DependFound) {
11206 if (DSAStack->doesParentHasOrderedDirective()) {
11207 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11208 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11209 diag::note_omp_previous_directive)
11210 << "ordered";
11211 return StmtError();
11212 }
11213 DSAStack->setParentHasOrderedDirective(StartLoc);
11214 }
11215
11216 if (AStmt) {
11217 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11218
11220 }
11221
11222 return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11223}
11224
11225namespace {
11226/// Helper class for checking expression in 'omp atomic [update]'
11227/// construct.
11228class OpenMPAtomicUpdateChecker {
11229 /// Error results for atomic update expressions.
11230 enum ExprAnalysisErrorCode {
11231 /// A statement is not an expression statement.
11232 NotAnExpression,
11233 /// Expression is not builtin binary or unary operation.
11234 NotABinaryOrUnaryExpression,
11235 /// Unary operation is not post-/pre- increment/decrement operation.
11236 NotAnUnaryIncDecExpression,
11237 /// An expression is not of scalar type.
11238 NotAScalarType,
11239 /// A binary operation is not an assignment operation.
11240 NotAnAssignmentOp,
11241 /// RHS part of the binary operation is not a binary expression.
11242 NotABinaryExpression,
11243 /// RHS part is not additive/multiplicative/shift/biwise binary
11244 /// expression.
11245 NotABinaryOperator,
11246 /// RHS binary operation does not have reference to the updated LHS
11247 /// part.
11248 NotAnUpdateExpression,
11249 /// No errors is found.
11250 NoError
11251 };
11252 /// Reference to Sema.
11253 Sema &SemaRef;
11254 /// A location for note diagnostics (when error is found).
11255 SourceLocation NoteLoc;
11256 /// 'x' lvalue part of the source atomic expression.
11257 Expr *X;
11258 /// 'expr' rvalue part of the source atomic expression.
11259 Expr *E;
11260 /// Helper expression of the form
11261 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11262 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11263 Expr *UpdateExpr;
11264 /// Is 'x' a LHS in a RHS part of full update expression. It is
11265 /// important for non-associative operations.
11266 bool IsXLHSInRHSPart;
11268 SourceLocation OpLoc;
11269 /// true if the source expression is a postfix unary operation, false
11270 /// if it is a prefix unary operation.
11271 bool IsPostfixUpdate;
11272
11273public:
11274 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11275 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11276 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11277 /// Check specified statement that it is suitable for 'atomic update'
11278 /// constructs and extract 'x', 'expr' and Operation from the original
11279 /// expression. If DiagId and NoteId == 0, then only check is performed
11280 /// without error notification.
11281 /// \param DiagId Diagnostic which should be emitted if error is found.
11282 /// \param NoteId Diagnostic note for the main error message.
11283 /// \return true if statement is not an update expression, false otherwise.
11284 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11285 /// Return the 'x' lvalue part of the source atomic expression.
11286 Expr *getX() const { return X; }
11287 /// Return the 'expr' rvalue part of the source atomic expression.
11288 Expr *getExpr() const { return E; }
11289 /// Return the update expression used in calculation of the updated
11290 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11291 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11292 Expr *getUpdateExpr() const { return UpdateExpr; }
11293 /// Return true if 'x' is LHS in RHS part of full update expression,
11294 /// false otherwise.
11295 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11296
11297 /// true if the source expression is a postfix unary operation, false
11298 /// if it is a prefix unary operation.
11299 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11300
11301private:
11302 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11303 unsigned NoteId = 0);
11304};
11305
11306bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11307 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11308 ExprAnalysisErrorCode ErrorFound = NoError;
11309 SourceLocation ErrorLoc, NoteLoc;
11310 SourceRange ErrorRange, NoteRange;
11311 // Allowed constructs are:
11312 // x = x binop expr;
11313 // x = expr binop x;
11314 if (AtomicBinOp->getOpcode() == BO_Assign) {
11315 X = AtomicBinOp->getLHS();
11316 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11317 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11318 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11319 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11320 AtomicInnerBinOp->isBitwiseOp()) {
11321 Op = AtomicInnerBinOp->getOpcode();
11322 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11323 Expr *LHS = AtomicInnerBinOp->getLHS();
11324 Expr *RHS = AtomicInnerBinOp->getRHS();
11325 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11326 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11327 /*Canonical=*/true);
11328 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11329 /*Canonical=*/true);
11330 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11331 /*Canonical=*/true);
11332 if (XId == LHSId) {
11333 E = RHS;
11334 IsXLHSInRHSPart = true;
11335 } else if (XId == RHSId) {
11336 E = LHS;
11337 IsXLHSInRHSPart = false;
11338 } else {
11339 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11340 ErrorRange = AtomicInnerBinOp->getSourceRange();
11341 NoteLoc = X->getExprLoc();
11342 NoteRange = X->getSourceRange();
11343 ErrorFound = NotAnUpdateExpression;
11344 }
11345 } else {
11346 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11347 ErrorRange = AtomicInnerBinOp->getSourceRange();
11348 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11349 NoteRange = SourceRange(NoteLoc, NoteLoc);
11350 ErrorFound = NotABinaryOperator;
11351 }
11352 } else {
11353 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11354 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11355 ErrorFound = NotABinaryExpression;
11356 }
11357 } else {
11358 ErrorLoc = AtomicBinOp->getExprLoc();
11359 ErrorRange = AtomicBinOp->getSourceRange();
11360 NoteLoc = AtomicBinOp->getOperatorLoc();
11361 NoteRange = SourceRange(NoteLoc, NoteLoc);
11362 ErrorFound = NotAnAssignmentOp;
11363 }
11364 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11365 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11366 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11367 return true;
11368 }
11369 if (SemaRef.CurContext->isDependentContext())
11370 E = X = UpdateExpr = nullptr;
11371 return ErrorFound != NoError;
11372}
11373
11374bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11375 unsigned NoteId) {
11376 ExprAnalysisErrorCode ErrorFound = NoError;
11377 SourceLocation ErrorLoc, NoteLoc;
11378 SourceRange ErrorRange, NoteRange;
11379 // Allowed constructs are:
11380 // x++;
11381 // x--;
11382 // ++x;
11383 // --x;
11384 // x binop= expr;
11385 // x = x binop expr;
11386 // x = expr binop x;
11387 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11388 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11389 if (AtomicBody->getType()->isScalarType() ||
11390 AtomicBody->isInstantiationDependent()) {
11391 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11392 AtomicBody->IgnoreParenImpCasts())) {
11393 // Check for Compound Assignment Operation
11395 AtomicCompAssignOp->getOpcode());
11396 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11397 E = AtomicCompAssignOp->getRHS();
11398 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11399 IsXLHSInRHSPart = true;
11400 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11401 AtomicBody->IgnoreParenImpCasts())) {
11402 // Check for Binary Operation
11403 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11404 return true;
11405 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11406 AtomicBody->IgnoreParenImpCasts())) {
11407 // Check for Unary Operation
11408 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11409 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11410 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11411 OpLoc = AtomicUnaryOp->getOperatorLoc();
11412 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11413 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11414 IsXLHSInRHSPart = true;
11415 } else {
11416 ErrorFound = NotAnUnaryIncDecExpression;
11417 ErrorLoc = AtomicUnaryOp->getExprLoc();
11418 ErrorRange = AtomicUnaryOp->getSourceRange();
11419 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11420 NoteRange = SourceRange(NoteLoc, NoteLoc);
11421 }
11422 } else if (!AtomicBody->isInstantiationDependent()) {
11423 ErrorFound = NotABinaryOrUnaryExpression;
11424 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11425 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11426 }
11427 } else {
11428 ErrorFound = NotAScalarType;
11429 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11430 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11431 }
11432 } else {
11433 ErrorFound = NotAnExpression;
11434 NoteLoc = ErrorLoc = S->getBeginLoc();
11435 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11436 }
11437 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11438 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11439 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11440 return true;
11441 }
11442 if (SemaRef.CurContext->isDependentContext())
11443 E = X = UpdateExpr = nullptr;
11444 if (ErrorFound == NoError && E && X) {
11445 // Build an update expression of form 'OpaqueValueExpr(x) binop
11446 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11447 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11448 auto *OVEX = new (SemaRef.getASTContext())
11449 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11450 auto *OVEExpr = new (SemaRef.getASTContext())
11453 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11454 IsXLHSInRHSPart ? OVEExpr : OVEX);
11455 if (Update.isInvalid())
11456 return true;
11457 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11459 if (Update.isInvalid())
11460 return true;
11461 UpdateExpr = Update.get();
11462 }
11463 return ErrorFound != NoError;
11464}
11465
11466/// Get the node id of the fixed point of an expression \a S.
11467llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11468 llvm::FoldingSetNodeID Id;
11469 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11470 return Id;
11471}
11472
11473/// Check if two expressions are same.
11474bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11475 const Expr *RHS) {
11476 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11477}
11478
11479class OpenMPAtomicCompareChecker {
11480public:
11481 /// All kinds of errors that can occur in `atomic compare`
11482 enum ErrorTy {
11483 /// Empty compound statement.
11484 NoStmt = 0,
11485 /// More than one statement in a compound statement.
11486 MoreThanOneStmt,
11487 /// Not an assignment binary operator.
11488 NotAnAssignment,
11489 /// Not a conditional operator.
11490 NotCondOp,
11491 /// Wrong false expr. According to the spec, 'x' should be at the false
11492 /// expression of a conditional expression.
11493 WrongFalseExpr,
11494 /// The condition of a conditional expression is not a binary operator.
11495 NotABinaryOp,
11496 /// Invalid binary operator (not <, >, or ==).
11497 InvalidBinaryOp,
11498 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11499 InvalidComparison,
11500 /// X is not a lvalue.
11501 XNotLValue,
11502 /// Not a scalar.
11503 NotScalar,
11504 /// Not an integer.
11505 NotInteger,
11506 /// 'else' statement is not expected.
11507 UnexpectedElse,
11508 /// Not an equality operator.
11509 NotEQ,
11510 /// Invalid assignment (not v == x).
11511 InvalidAssignment,
11512 /// Not if statement
11513 NotIfStmt,
11514 /// More than two statements in a compund statement.
11515 MoreThanTwoStmts,
11516 /// Not a compound statement.
11517 NotCompoundStmt,
11518 /// No else statement.
11519 NoElse,
11520 /// Not 'if (r)'.
11521 InvalidCondition,
11522 /// No error.
11523 NoError,
11524 };
11525
11526 struct ErrorInfoTy {
11527 ErrorTy Error;
11528 SourceLocation ErrorLoc;
11529 SourceRange ErrorRange;
11530 SourceLocation NoteLoc;
11531 SourceRange NoteRange;
11532 };
11533
11534 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11535
11536 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11537 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11538
11539 Expr *getX() const { return X; }
11540 Expr *getE() const { return E; }
11541 Expr *getD() const { return D; }
11542 Expr *getCond() const { return C; }
11543 bool isXBinopExpr() const { return IsXBinopExpr; }
11544
11545protected:
11546 /// Reference to ASTContext
11547 ASTContext &ContextRef;
11548 /// 'x' lvalue part of the source atomic expression.
11549 Expr *X = nullptr;
11550 /// 'expr' or 'e' rvalue part of the source atomic expression.
11551 Expr *E = nullptr;
11552 /// 'd' rvalue part of the source atomic expression.
11553 Expr *D = nullptr;
11554 /// 'cond' part of the source atomic expression. It is in one of the following
11555 /// forms:
11556 /// expr ordop x
11557 /// x ordop expr
11558 /// x == e
11559 /// e == x
11560 Expr *C = nullptr;
11561 /// True if the cond expr is in the form of 'x ordop expr'.
11562 bool IsXBinopExpr = true;
11563
11564 /// Check if it is a valid conditional update statement (cond-update-stmt).
11565 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11566
11567 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11568 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11569
11570 /// Check if all captured values have right type.
11571 bool checkType(ErrorInfoTy &ErrorInfo) const;
11572
11573 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11574 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11575 if (ShouldBeLValue && !E->isLValue()) {
11576 ErrorInfo.Error = ErrorTy::XNotLValue;
11577 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11578 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11579 return false;
11580 }
11581
11582 if (!E->isInstantiationDependent()) {
11583 QualType QTy = E->getType();
11584 if (!QTy->isScalarType()) {
11585 ErrorInfo.Error = ErrorTy::NotScalar;
11586 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11587 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11588 return false;
11589 }
11590 if (ShouldBeInteger && !QTy->isIntegerType()) {
11591 ErrorInfo.Error = ErrorTy::NotInteger;
11592 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11593 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11594 return false;
11595 }
11596 }
11597
11598 return true;
11599 }
11600};
11601
11602bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11603 ErrorInfoTy &ErrorInfo) {
11604 auto *Then = S->getThen();
11605 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11606 if (CS->body_empty()) {
11607 ErrorInfo.Error = ErrorTy::NoStmt;
11608 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11609 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11610 return false;
11611 }
11612 if (CS->size() > 1) {
11613 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11614 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11615 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11616 return false;
11617 }
11618 Then = CS->body_front();
11619 }
11620
11621 auto *BO = dyn_cast<BinaryOperator>(Then);
11622 if (!BO) {
11623 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11624 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11625 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11626 return false;
11627 }
11628 if (BO->getOpcode() != BO_Assign) {
11629 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11630 ErrorInfo.ErrorLoc = BO->getExprLoc();
11631 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11632 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11633 return false;
11634 }
11635
11636 X = BO->getLHS();
11637
11638 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11639 if (!Cond) {
11640 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11641 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11642 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11643 return false;
11644 }
11645
11646 switch (Cond->getOpcode()) {
11647 case BO_EQ: {
11648 C = Cond;
11649 D = BO->getRHS();
11650 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11651 E = Cond->getRHS();
11652 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11653 E = Cond->getLHS();
11654 } else {
11655 ErrorInfo.Error = ErrorTy::InvalidComparison;
11656 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11657 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11658 return false;
11659 }
11660 break;
11661 }
11662 case BO_LT:
11663 case BO_GT: {
11664 E = BO->getRHS();
11665 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11666 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11667 C = Cond;
11668 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11669 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11670 C = Cond;
11671 IsXBinopExpr = false;
11672 } else {
11673 ErrorInfo.Error = ErrorTy::InvalidComparison;
11674 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11675 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11676 return false;
11677 }
11678 break;
11679 }
11680 default:
11681 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11682 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11683 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11684 return false;
11685 }
11686
11687 if (S->getElse()) {
11688 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11689 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11690 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11691 return false;
11692 }
11693
11694 return true;
11695}
11696
11697bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11698 ErrorInfoTy &ErrorInfo) {
11699 auto *BO = dyn_cast<BinaryOperator>(S);
11700 if (!BO) {
11701 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11702 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11703 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11704 return false;
11705 }
11706 if (BO->getOpcode() != BO_Assign) {
11707 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11708 ErrorInfo.ErrorLoc = BO->getExprLoc();
11709 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11710 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11711 return false;
11712 }
11713
11714 X = BO->getLHS();
11715
11716 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11717 if (!CO) {
11718 ErrorInfo.Error = ErrorTy::NotCondOp;
11719 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11720 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11721 return false;
11722 }
11723
11724 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11725 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11726 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11727 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11728 CO->getFalseExpr()->getSourceRange();
11729 return false;
11730 }
11731
11732 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11733 if (!Cond) {
11734 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11735 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11736 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11737 CO->getCond()->getSourceRange();
11738 return false;
11739 }
11740
11741 switch (Cond->getOpcode()) {
11742 case BO_EQ: {
11743 C = Cond;
11744 D = CO->getTrueExpr();
11745 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11746 E = Cond->getRHS();
11747 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11748 E = Cond->getLHS();
11749 } else {
11750 ErrorInfo.Error = ErrorTy::InvalidComparison;
11751 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11752 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11753 return false;
11754 }
11755 break;
11756 }
11757 case BO_LT:
11758 case BO_GT: {
11759 E = CO->getTrueExpr();
11760 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11761 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11762 C = Cond;
11763 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11764 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11765 C = Cond;
11766 IsXBinopExpr = false;
11767 } else {
11768 ErrorInfo.Error = ErrorTy::InvalidComparison;
11769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11771 return false;
11772 }
11773 break;
11774 }
11775 default:
11776 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11777 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11778 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11779 return false;
11780 }
11781
11782 return true;
11783}
11784
11785bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11786 // 'x' and 'e' cannot be nullptr
11787 assert(X && E && "X and E cannot be nullptr");
11788
11789 if (!CheckValue(X, ErrorInfo, true))
11790 return false;
11791
11792 if (!CheckValue(E, ErrorInfo, false))
11793 return false;
11794
11795 if (D && !CheckValue(D, ErrorInfo, false))
11796 return false;
11797
11798 return true;
11799}
11800
11801bool OpenMPAtomicCompareChecker::checkStmt(
11802 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11803 auto *CS = dyn_cast<CompoundStmt>(S);
11804 if (CS) {
11805 if (CS->body_empty()) {
11806 ErrorInfo.Error = ErrorTy::NoStmt;
11807 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11808 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11809 return false;
11810 }
11811
11812 if (CS->size() != 1) {
11813 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11814 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11815 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11816 return false;
11817 }
11818 S = CS->body_front();
11819 }
11820
11821 auto Res = false;
11822
11823 if (auto *IS = dyn_cast<IfStmt>(S)) {
11824 // Check if the statement is in one of the following forms
11825 // (cond-update-stmt):
11826 // if (expr ordop x) { x = expr; }
11827 // if (x ordop expr) { x = expr; }
11828 // if (x == e) { x = d; }
11829 Res = checkCondUpdateStmt(IS, ErrorInfo);
11830 } else {
11831 // Check if the statement is in one of the following forms (cond-expr-stmt):
11832 // x = expr ordop x ? expr : x;
11833 // x = x ordop expr ? expr : x;
11834 // x = x == e ? d : x;
11835 Res = checkCondExprStmt(S, ErrorInfo);
11836 }
11837
11838 if (!Res)
11839 return false;
11840
11841 return checkType(ErrorInfo);
11842}
11843
11844class OpenMPAtomicCompareCaptureChecker final
11845 : public OpenMPAtomicCompareChecker {
11846public:
11847 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11848
11849 Expr *getV() const { return V; }
11850 Expr *getR() const { return R; }
11851 bool isFailOnly() const { return IsFailOnly; }
11852 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11853
11854 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11855 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11856
11857private:
11858 bool checkType(ErrorInfoTy &ErrorInfo);
11859
11860 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11861 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11862 // spec p.p. 82:
11863 // (1) { v = x; cond-update-stmt }
11864 // (2) { cond-update-stmt v = x; }
11865 // (3) if(x == e) { x = d; } else { v = x; }
11866 // (4) { r = x == e; if(r) { x = d; } }
11867 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11868
11869 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11870 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11871
11872 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11873 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11874 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11875
11876 /// 'v' lvalue part of the source atomic expression.
11877 Expr *V = nullptr;
11878 /// 'r' lvalue part of the source atomic expression.
11879 Expr *R = nullptr;
11880 /// If 'v' is only updated when the comparison fails.
11881 bool IsFailOnly = false;
11882 /// If original value of 'x' must be stored in 'v', not an updated one.
11883 bool IsPostfixUpdate = false;
11884};
11885
11886bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11887 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11888 return false;
11889
11890 if (V && !CheckValue(V, ErrorInfo, true))
11891 return false;
11892
11893 if (R && !CheckValue(R, ErrorInfo, true, true))
11894 return false;
11895
11896 return true;
11897}
11898
11899bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11900 ErrorInfoTy &ErrorInfo) {
11901 IsFailOnly = true;
11902
11903 auto *Then = S->getThen();
11904 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11905 if (CS->body_empty()) {
11906 ErrorInfo.Error = ErrorTy::NoStmt;
11907 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11908 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11909 return false;
11910 }
11911 if (CS->size() > 1) {
11912 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11913 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11914 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11915 return false;
11916 }
11917 Then = CS->body_front();
11918 }
11919
11920 auto *BO = dyn_cast<BinaryOperator>(Then);
11921 if (!BO) {
11922 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11923 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11924 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11925 return false;
11926 }
11927 if (BO->getOpcode() != BO_Assign) {
11928 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11929 ErrorInfo.ErrorLoc = BO->getExprLoc();
11930 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11931 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11932 return false;
11933 }
11934
11935 X = BO->getLHS();
11936 D = BO->getRHS();
11937
11938 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11939 if (!Cond) {
11940 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11941 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11942 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11943 return false;
11944 }
11945 if (Cond->getOpcode() != BO_EQ) {
11946 ErrorInfo.Error = ErrorTy::NotEQ;
11947 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11948 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11949 return false;
11950 }
11951
11952 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11953 E = Cond->getRHS();
11954 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11955 E = Cond->getLHS();
11956 } else {
11957 ErrorInfo.Error = ErrorTy::InvalidComparison;
11958 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11959 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11960 return false;
11961 }
11962
11963 C = Cond;
11964
11965 if (!S->getElse()) {
11966 ErrorInfo.Error = ErrorTy::NoElse;
11967 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11968 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11969 return false;
11970 }
11971
11972 auto *Else = S->getElse();
11973 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
11974 if (CS->body_empty()) {
11975 ErrorInfo.Error = ErrorTy::NoStmt;
11976 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11977 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11978 return false;
11979 }
11980 if (CS->size() > 1) {
11981 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11982 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11983 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11984 return false;
11985 }
11986 Else = CS->body_front();
11987 }
11988
11989 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
11990 if (!ElseBO) {
11991 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11992 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
11993 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
11994 return false;
11995 }
11996 if (ElseBO->getOpcode() != BO_Assign) {
11997 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11998 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
11999 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12000 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12001 return false;
12002 }
12003
12004 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12005 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12006 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12007 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12008 ElseBO->getRHS()->getSourceRange();
12009 return false;
12010 }
12011
12012 V = ElseBO->getLHS();
12013
12014 return checkType(ErrorInfo);
12015}
12016
12017bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12018 ErrorInfoTy &ErrorInfo) {
12019 // We don't check here as they should be already done before call this
12020 // function.
12021 auto *CS = cast<CompoundStmt>(S);
12022 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12023 auto *S1 = cast<BinaryOperator>(CS->body_front());
12024 auto *S2 = cast<IfStmt>(CS->body_back());
12025 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12026
12027 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12028 ErrorInfo.Error = ErrorTy::InvalidCondition;
12029 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12030 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12031 return false;
12032 }
12033
12034 R = S1->getLHS();
12035
12036 auto *Then = S2->getThen();
12037 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12038 if (ThenCS->body_empty()) {
12039 ErrorInfo.Error = ErrorTy::NoStmt;
12040 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12041 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12042 return false;
12043 }
12044 if (ThenCS->size() > 1) {
12045 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12046 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12047 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12048 return false;
12049 }
12050 Then = ThenCS->body_front();
12051 }
12052
12053 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12054 if (!ThenBO) {
12055 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12056 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12058 return false;
12059 }
12060 if (ThenBO->getOpcode() != BO_Assign) {
12061 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12062 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12063 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12064 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12065 return false;
12066 }
12067
12068 X = ThenBO->getLHS();
12069 D = ThenBO->getRHS();
12070
12071 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12072 if (BO->getOpcode() != BO_EQ) {
12073 ErrorInfo.Error = ErrorTy::NotEQ;
12074 ErrorInfo.ErrorLoc = BO->getExprLoc();
12075 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12076 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12077 return false;
12078 }
12079
12080 C = BO;
12081
12082 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12083 E = BO->getRHS();
12084 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12085 E = BO->getLHS();
12086 } else {
12087 ErrorInfo.Error = ErrorTy::InvalidComparison;
12088 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12089 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12090 return false;
12091 }
12092
12093 if (S2->getElse()) {
12094 IsFailOnly = true;
12095
12096 auto *Else = S2->getElse();
12097 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12098 if (ElseCS->body_empty()) {
12099 ErrorInfo.Error = ErrorTy::NoStmt;
12100 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12101 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12102 return false;
12103 }
12104 if (ElseCS->size() > 1) {
12105 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12106 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12107 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12108 return false;
12109 }
12110 Else = ElseCS->body_front();
12111 }
12112
12113 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12114 if (!ElseBO) {
12115 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12116 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12117 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12118 return false;
12119 }
12120 if (ElseBO->getOpcode() != BO_Assign) {
12121 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12122 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12123 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12124 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12125 return false;
12126 }
12127 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12128 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12129 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12130 ErrorInfo.NoteLoc = X->getExprLoc();
12131 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12132 ErrorInfo.NoteRange = X->getSourceRange();
12133 return false;
12134 }
12135
12136 V = ElseBO->getLHS();
12137 }
12138
12139 return checkType(ErrorInfo);
12140}
12141
12142bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12143 ErrorInfoTy &ErrorInfo) {
12144 // if(x == e) { x = d; } else { v = x; }
12145 if (auto *IS = dyn_cast<IfStmt>(S))
12146 return checkForm3(IS, ErrorInfo);
12147
12148 auto *CS = dyn_cast<CompoundStmt>(S);
12149 if (!CS) {
12150 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12151 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12152 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12153 return false;
12154 }
12155 if (CS->body_empty()) {
12156 ErrorInfo.Error = ErrorTy::NoStmt;
12157 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12158 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12159 return false;
12160 }
12161
12162 // { if(x == e) { x = d; } else { v = x; } }
12163 if (CS->size() == 1) {
12164 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12165 if (!IS) {
12166 ErrorInfo.Error = ErrorTy::NotIfStmt;
12167 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12168 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12169 CS->body_front()->getSourceRange();
12170 return false;
12171 }
12172
12173 return checkForm3(IS, ErrorInfo);
12174 } else if (CS->size() == 2) {
12175 auto *S1 = CS->body_front();
12176 auto *S2 = CS->body_back();
12177
12178 Stmt *UpdateStmt = nullptr;
12179 Stmt *CondUpdateStmt = nullptr;
12180
12181 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12182 // { v = x; cond-update-stmt } or form 45.
12183 UpdateStmt = S1;
12184 CondUpdateStmt = S2;
12185 // Check if form 45.
12186 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) &&
12187 isa<IfStmt>(S2))
12188 return checkForm45(CS, ErrorInfo);
12189 // It cannot be set before we the check for form45.
12190 IsPostfixUpdate = true;
12191 } else {
12192 // { cond-update-stmt v = x; }
12193 UpdateStmt = S2;
12194 CondUpdateStmt = S1;
12195 }
12196
12197 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12198 auto *IS = dyn_cast<IfStmt>(CUS);
12199 if (!IS) {
12200 ErrorInfo.Error = ErrorTy::NotIfStmt;
12201 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12202 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12203 return false;
12204 }
12205
12206 if (!checkCondUpdateStmt(IS, ErrorInfo))
12207 return false;
12208
12209 return true;
12210 };
12211
12212 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12213 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12214 auto *BO = dyn_cast<BinaryOperator>(US);
12215 if (!BO) {
12216 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12217 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12218 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12219 return false;
12220 }
12221 if (BO->getOpcode() != BO_Assign) {
12222 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12223 ErrorInfo.ErrorLoc = BO->getExprLoc();
12224 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12225 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12226 return false;
12227 }
12228 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12229 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12230 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12231 ErrorInfo.NoteLoc = this->X->getExprLoc();
12232 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12233 ErrorInfo.NoteRange = this->X->getSourceRange();
12234 return false;
12235 }
12236
12237 this->V = BO->getLHS();
12238
12239 return true;
12240 };
12241
12242 if (!CheckCondUpdateStmt(CondUpdateStmt))
12243 return false;
12244 if (!CheckUpdateStmt(UpdateStmt))
12245 return false;
12246 } else {
12247 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12248 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12249 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12250 return false;
12251 }
12252
12253 return checkType(ErrorInfo);
12254}
12255} // namespace
12256
12258 Stmt *AStmt,
12259 SourceLocation StartLoc,
12260 SourceLocation EndLoc) {
12261 // Register location of the first atomic directive.
12262 DSAStack->addAtomicDirectiveLoc(StartLoc);
12263 if (!AStmt)
12264 return StmtError();
12265
12266 // 1.2.2 OpenMP Language Terminology
12267 // Structured block - An executable statement with a single entry at the
12268 // top and a single exit at the bottom.
12269 // The point of exit cannot be a branch out of the structured block.
12270 // longjmp() and throw() must not violate the entry/exit criteria.
12271 OpenMPClauseKind AtomicKind = OMPC_unknown;
12272 SourceLocation AtomicKindLoc;
12273 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12274 SourceLocation MemOrderLoc;
12275 bool MutexClauseEncountered = false;
12276 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12277 for (const OMPClause *C : Clauses) {
12278 switch (C->getClauseKind()) {
12279 case OMPC_read:
12280 case OMPC_write:
12281 case OMPC_update:
12282 MutexClauseEncountered = true;
12283 LLVM_FALLTHROUGH;
12284 case OMPC_capture:
12285 case OMPC_compare: {
12286 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12287 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12288 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12289 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12290 << getOpenMPClauseName(AtomicKind);
12291 } else {
12292 AtomicKind = C->getClauseKind();
12293 AtomicKindLoc = C->getBeginLoc();
12294 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12295 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12296 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12297 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12298 << getOpenMPClauseName(AtomicKind);
12299 }
12300 }
12301 break;
12302 }
12303 case OMPC_seq_cst:
12304 case OMPC_acq_rel:
12305 case OMPC_acquire:
12306 case OMPC_release:
12307 case OMPC_relaxed: {
12308 if (MemOrderKind != OMPC_unknown) {
12309 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12310 << getOpenMPDirectiveName(OMPD_atomic) << 0
12311 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12312 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12313 << getOpenMPClauseName(MemOrderKind);
12314 } else {
12315 MemOrderKind = C->getClauseKind();
12316 MemOrderLoc = C->getBeginLoc();
12317 }
12318 break;
12319 }
12320 // The following clauses are allowed, but we don't need to do anything here.
12321 case OMPC_hint:
12322 break;
12323 default:
12324 llvm_unreachable("unknown clause is encountered");
12325 }
12326 }
12327 bool IsCompareCapture = false;
12328 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12329 EncounteredAtomicKinds.contains(OMPC_capture)) {
12330 IsCompareCapture = true;
12331 AtomicKind = OMPC_compare;
12332 }
12333 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12334 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12335 // release.
12336 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12337 // acquire.
12338 // If atomic-clause is update or not present then memory-order-clause must not
12339 // be acq_rel or acquire.
12340 if ((AtomicKind == OMPC_read &&
12341 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12342 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12343 AtomicKind == OMPC_unknown) &&
12344 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12345 SourceLocation Loc = AtomicKindLoc;
12346 if (AtomicKind == OMPC_unknown)
12347 Loc = StartLoc;
12348 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12349 << getOpenMPClauseName(AtomicKind)
12350 << (AtomicKind == OMPC_unknown ? 1 : 0)
12351 << getOpenMPClauseName(MemOrderKind);
12352 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12353 << getOpenMPClauseName(MemOrderKind);
12354 }
12355
12356 Stmt *Body = AStmt;
12357 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12358 Body = EWC->getSubExpr();
12359
12360 Expr *X = nullptr;
12361 Expr *V = nullptr;
12362 Expr *E = nullptr;
12363 Expr *UE = nullptr;
12364 Expr *D = nullptr;
12365 Expr *CE = nullptr;
12366 Expr *R = nullptr;
12367 bool IsXLHSInRHSPart = false;
12368 bool IsPostfixUpdate = false;
12369 bool IsFailOnly = false;
12370 // OpenMP [2.12.6, atomic Construct]
12371 // In the next expressions:
12372 // * x and v (as applicable) are both l-value expressions with scalar type.
12373 // * During the execution of an atomic region, multiple syntactic
12374 // occurrences of x must designate the same storage location.
12375 // * Neither of v and expr (as applicable) may access the storage location
12376 // designated by x.
12377 // * Neither of x and expr (as applicable) may access the storage location
12378 // designated by v.
12379 // * expr is an expression with scalar type.
12380 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12381 // * binop, binop=, ++, and -- are not overloaded operators.
12382 // * The expression x binop expr must be numerically equivalent to x binop
12383 // (expr). This requirement is satisfied if the operators in expr have
12384 // precedence greater than binop, or by using parentheses around expr or
12385 // subexpressions of expr.
12386 // * The expression expr binop x must be numerically equivalent to (expr)
12387 // binop x. This requirement is satisfied if the operators in expr have
12388 // precedence equal to or greater than binop, or by using parentheses around
12389 // expr or subexpressions of expr.
12390 // * For forms that allow multiple occurrences of x, the number of times
12391 // that x is evaluated is unspecified.
12392 if (AtomicKind == OMPC_read) {
12393 enum {
12394 NotAnExpression,
12395 NotAnAssignmentOp,
12396 NotAScalarType,
12397 NotAnLValue,
12398 NoError
12399 } ErrorFound = NoError;
12400 SourceLocation ErrorLoc, NoteLoc;
12401 SourceRange ErrorRange, NoteRange;
12402 // If clause is read:
12403 // v = x;
12404 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12405 const auto *AtomicBinOp =
12406 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12407 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12408 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12409 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12410 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12411 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12412 if (!X->isLValue() || !V->isLValue()) {
12413 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12414 ErrorFound = NotAnLValue;
12415 ErrorLoc = AtomicBinOp->getExprLoc();
12416 ErrorRange = AtomicBinOp->getSourceRange();
12417 NoteLoc = NotLValueExpr->getExprLoc();
12418 NoteRange = NotLValueExpr->getSourceRange();
12419 }
12420 } else if (!X->isInstantiationDependent() ||
12421 !V->isInstantiationDependent()) {
12422 const Expr *NotScalarExpr =
12423 (X->isInstantiationDependent() || X->getType()->isScalarType())
12424 ? V
12425 : X;
12426 ErrorFound = NotAScalarType;
12427 ErrorLoc = AtomicBinOp->getExprLoc();
12428 ErrorRange = AtomicBinOp->getSourceRange();
12429 NoteLoc = NotScalarExpr->getExprLoc();
12430 NoteRange = NotScalarExpr->getSourceRange();
12431 }
12432 } else if (!AtomicBody->isInstantiationDependent()) {
12433 ErrorFound = NotAnAssignmentOp;
12434 ErrorLoc = AtomicBody->getExprLoc();
12435 ErrorRange = AtomicBody->getSourceRange();
12436 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12437 : AtomicBody->getExprLoc();
12438 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12439 : AtomicBody->getSourceRange();
12440 }
12441 } else {
12442 ErrorFound = NotAnExpression;
12443 NoteLoc = ErrorLoc = Body->getBeginLoc();
12444 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12445 }
12446 if (ErrorFound != NoError) {
12447 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12448 << ErrorRange;
12449 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12450 << ErrorFound << NoteRange;
12451 return StmtError();
12452 }
12454 V = X = nullptr;
12455 } else if (AtomicKind == OMPC_write) {
12456 enum {
12457 NotAnExpression,
12458 NotAnAssignmentOp,
12459 NotAScalarType,
12460 NotAnLValue,
12461 NoError
12462 } ErrorFound = NoError;
12463 SourceLocation ErrorLoc, NoteLoc;
12464 SourceRange ErrorRange, NoteRange;
12465 // If clause is write:
12466 // x = expr;
12467 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12468 const auto *AtomicBinOp =
12469 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12470 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12471 X = AtomicBinOp->getLHS();
12472 E = AtomicBinOp->getRHS();
12473 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12474 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12475 if (!X->isLValue()) {
12476 ErrorFound = NotAnLValue;
12477 ErrorLoc = AtomicBinOp->getExprLoc();
12478 ErrorRange = AtomicBinOp->getSourceRange();
12479 NoteLoc = X->getExprLoc();
12480 NoteRange = X->getSourceRange();
12481 }
12482 } else if (!X->isInstantiationDependent() ||
12484 const Expr *NotScalarExpr =
12485 (X->isInstantiationDependent() || X->getType()->isScalarType())
12486 ? E
12487 : X;
12488 ErrorFound = NotAScalarType;
12489 ErrorLoc = AtomicBinOp->getExprLoc();
12490 ErrorRange = AtomicBinOp->getSourceRange();
12491 NoteLoc = NotScalarExpr->getExprLoc();
12492 NoteRange = NotScalarExpr->getSourceRange();
12493 }
12494 } else if (!AtomicBody->isInstantiationDependent()) {
12495 ErrorFound = NotAnAssignmentOp;
12496 ErrorLoc = AtomicBody->getExprLoc();
12497 ErrorRange = AtomicBody->getSourceRange();
12498 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12499 : AtomicBody->getExprLoc();
12500 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12501 : AtomicBody->getSourceRange();
12502 }
12503 } else {
12504 ErrorFound = NotAnExpression;
12505 NoteLoc = ErrorLoc = Body->getBeginLoc();
12506 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12507 }
12508 if (ErrorFound != NoError) {
12509 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12510 << ErrorRange;
12511 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12512 << ErrorFound << NoteRange;
12513 return StmtError();
12514 }
12516 E = X = nullptr;
12517 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12518 // If clause is update:
12519 // x++;
12520 // x--;
12521 // ++x;
12522 // --x;
12523 // x binop= expr;
12524 // x = x binop expr;
12525 // x = expr binop x;
12526 OpenMPAtomicUpdateChecker Checker(*this);
12527 if (Checker.checkStatement(
12528 Body,
12529 (AtomicKind == OMPC_update)
12530 ? diag::err_omp_atomic_update_not_expression_statement
12531 : diag::err_omp_atomic_not_expression_statement,
12532 diag::note_omp_atomic_update))
12533 return StmtError();
12535 E = Checker.getExpr();
12536 X = Checker.getX();
12537 UE = Checker.getUpdateExpr();
12538 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12539 }
12540 } else if (AtomicKind == OMPC_capture) {
12541 enum {
12542 NotAnAssignmentOp,
12543 NotACompoundStatement,
12544 NotTwoSubstatements,
12545 NotASpecificExpression,
12546 NoError
12547 } ErrorFound = NoError;
12548 SourceLocation ErrorLoc, NoteLoc;
12549 SourceRange ErrorRange, NoteRange;
12550 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12551 // If clause is a capture:
12552 // v = x++;
12553 // v = x--;
12554 // v = ++x;
12555 // v = --x;
12556 // v = x binop= expr;
12557 // v = x = x binop expr;
12558 // v = x = expr binop x;
12559 const auto *AtomicBinOp =
12560 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12561 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12562 V = AtomicBinOp->getLHS();
12563 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12564 OpenMPAtomicUpdateChecker Checker(*this);
12565 if (Checker.checkStatement(
12566 Body, diag::err_omp_atomic_capture_not_expression_statement,
12567 diag::note_omp_atomic_update))
12568 return StmtError();
12569 E = Checker.getExpr();
12570 X = Checker.getX();
12571 UE = Checker.getUpdateExpr();
12572 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12573 IsPostfixUpdate = Checker.isPostfixUpdate();
12574 } else if (!AtomicBody->isInstantiationDependent()) {
12575 ErrorLoc = AtomicBody->getExprLoc();
12576 ErrorRange = AtomicBody->getSourceRange();
12577 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12578 : AtomicBody->getExprLoc();
12579 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12580 : AtomicBody->getSourceRange();
12581 ErrorFound = NotAnAssignmentOp;
12582 }
12583 if (ErrorFound != NoError) {
12584 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12585 << ErrorRange;
12586 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12587 return StmtError();
12588 }
12590 UE = V = E = X = nullptr;
12591 } else {
12592 // If clause is a capture:
12593 // { v = x; x = expr; }
12594 // { v = x; x++; }
12595 // { v = x; x--; }
12596 // { v = x; ++x; }
12597 // { v = x; --x; }
12598 // { v = x; x binop= expr; }
12599 // { v = x; x = x binop expr; }
12600 // { v = x; x = expr binop x; }
12601 // { x++; v = x; }
12602 // { x--; v = x; }
12603 // { ++x; v = x; }
12604 // { --x; v = x; }
12605 // { x binop= expr; v = x; }
12606 // { x = x binop expr; v = x; }
12607 // { x = expr binop x; v = x; }
12608 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12609 // Check that this is { expr1; expr2; }
12610 if (CS->size() == 2) {
12611 Stmt *First = CS->body_front();
12612 Stmt *Second = CS->body_back();
12613 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12614 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12615 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12616 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12617 // Need to find what subexpression is 'v' and what is 'x'.
12618 OpenMPAtomicUpdateChecker Checker(*this);
12619 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12620 BinaryOperator *BinOp = nullptr;
12621 if (IsUpdateExprFound) {
12622 BinOp = dyn_cast<BinaryOperator>(First);
12623 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12624 }
12625 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12626 // { v = x; x++; }
12627 // { v = x; x--; }
12628 // { v = x; ++x; }
12629 // { v = x; --x; }
12630 // { v = x; x binop= expr; }
12631 // { v = x; x = x binop expr; }
12632 // { v = x; x = expr binop x; }
12633 // Check that the first expression has form v = x.
12634 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12635 llvm::FoldingSetNodeID XId, PossibleXId;
12636 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12637 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12638 IsUpdateExprFound = XId == PossibleXId;
12639 if (IsUpdateExprFound) {
12640 V = BinOp->getLHS();
12641 X = Checker.getX();
12642 E = Checker.getExpr();
12643 UE = Checker.getUpdateExpr();
12644 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12645 IsPostfixUpdate = true;
12646 }
12647 }
12648 if (!IsUpdateExprFound) {
12649 IsUpdateExprFound = !Checker.checkStatement(First);
12650 BinOp = nullptr;
12651 if (IsUpdateExprFound) {
12652 BinOp = dyn_cast<BinaryOperator>(Second);
12653 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12654 }
12655 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12656 // { x++; v = x; }
12657 // { x--; v = x; }
12658 // { ++x; v = x; }
12659 // { --x; v = x; }
12660 // { x binop= expr; v = x; }
12661 // { x = x binop expr; v = x; }
12662 // { x = expr binop x; v = x; }
12663 // Check that the second expression has form v = x.
12664 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12665 llvm::FoldingSetNodeID XId, PossibleXId;
12666 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12667 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12668 IsUpdateExprFound = XId == PossibleXId;
12669 if (IsUpdateExprFound) {
12670 V = BinOp->getLHS();
12671 X = Checker.getX();
12672 E = Checker.getExpr();
12673 UE = Checker.getUpdateExpr();
12674 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12675 IsPostfixUpdate = false;
12676 }
12677 }
12678 }
12679 if (!IsUpdateExprFound) {
12680 // { v = x; x = expr; }
12681 auto *FirstExpr = dyn_cast<Expr>(First);
12682 auto *SecondExpr = dyn_cast<Expr>(Second);
12683 if (!FirstExpr || !SecondExpr ||
12684 !(FirstExpr->isInstantiationDependent() ||
12685 SecondExpr->isInstantiationDependent())) {
12686 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12687 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12688 ErrorFound = NotAnAssignmentOp;
12689 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12690 : First->getBeginLoc();
12691 NoteRange = ErrorRange = FirstBinOp
12692 ? FirstBinOp->getSourceRange()
12693 : SourceRange(ErrorLoc, ErrorLoc);
12694 } else {
12695 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12696 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12697 ErrorFound = NotAnAssignmentOp;
12698 NoteLoc = ErrorLoc = SecondBinOp
12699 ? SecondBinOp->getOperatorLoc()
12700 : Second->getBeginLoc();
12701 NoteRange = ErrorRange =
12702 SecondBinOp ? SecondBinOp->getSourceRange()
12703 : SourceRange(ErrorLoc, ErrorLoc);
12704 } else {
12705 Expr *PossibleXRHSInFirst =
12706 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12707 Expr *PossibleXLHSInSecond =
12708 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12709 llvm::FoldingSetNodeID X1Id, X2Id;
12710 PossibleXRHSInFirst->Profile(X1Id, Context,
12711 /*Canonical=*/true);
12712 PossibleXLHSInSecond->Profile(X2Id, Context,
12713 /*Canonical=*/true);
12714 IsUpdateExprFound = X1Id == X2Id;
12715 if (IsUpdateExprFound) {
12716 V = FirstBinOp->getLHS();
12717 X = SecondBinOp->getLHS();
12718 E = SecondBinOp->getRHS();
12719 UE = nullptr;
12720 IsXLHSInRHSPart = false;
12721 IsPostfixUpdate = true;
12722 } else {
12723 ErrorFound = NotASpecificExpression;
12724 ErrorLoc = FirstBinOp->getExprLoc();
12725 ErrorRange = FirstBinOp->getSourceRange();
12726 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12727 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12728 }
12729 }
12730 }
12731 }
12732 }
12733 } else {
12734 NoteLoc = ErrorLoc = Body->getBeginLoc();
12735 NoteRange = ErrorRange =
12736 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12737 ErrorFound = NotTwoSubstatements;
12738 }
12739 } else {
12740 NoteLoc = ErrorLoc = Body->getBeginLoc();
12741 NoteRange = ErrorRange =
12742 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12743 ErrorFound = NotACompoundStatement;
12744 }
12745 }
12746 if (ErrorFound != NoError) {
12747 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12748 << ErrorRange;
12749 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12750 return StmtError();
12751 }
12753 UE = V = E = X = nullptr;
12754 } else if (AtomicKind == OMPC_compare) {
12755 if (IsCompareCapture) {
12756 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12757 OpenMPAtomicCompareCaptureChecker Checker(*this);
12758 if (!Checker.checkStmt(Body, ErrorInfo)) {
12759 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12760 << ErrorInfo.ErrorRange;
12761 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12762 << ErrorInfo.Error << ErrorInfo.NoteRange;
12763 return StmtError();
12764 }
12765 X = Checker.getX();
12766 E = Checker.getE();
12767 D = Checker.getD();
12768 CE = Checker.getCond();
12769 V = Checker.getV();
12770 R = Checker.getR();
12771 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12772 IsXLHSInRHSPart = Checker.isXBinopExpr();
12773 IsFailOnly = Checker.isFailOnly();
12774 IsPostfixUpdate = Checker.isPostfixUpdate();
12775 } else {
12776 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12777 OpenMPAtomicCompareChecker Checker(*this);
12778 if (!Checker.checkStmt(Body, ErrorInfo)) {
12779 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12780 << ErrorInfo.ErrorRange;
12781 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12782 << ErrorInfo.Error << ErrorInfo.NoteRange;
12783 return StmtError();
12784 }
12785 X = Checker.getX();
12786 E = Checker.getE();
12787 D = Checker.getD();
12788 CE = Checker.getCond();
12789 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12790 IsXLHSInRHSPart = Checker.isXBinopExpr();
12791 }
12792 }
12793
12795
12796 return OMPAtomicDirective::Create(
12797 Context, StartLoc, EndLoc, Clauses, AStmt,
12798 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12799}
12800
12802 Stmt *AStmt,
12803 SourceLocation StartLoc,
12804 SourceLocation EndLoc) {
12805 if (!AStmt)
12806 return StmtError();
12807
12808 auto *CS = cast<CapturedStmt>(AStmt);
12809 // 1.2.2 OpenMP Language Terminology
12810 // Structured block - An executable statement with a single entry at the
12811 // top and a single exit at the bottom.
12812 // The point of exit cannot be a branch out of the structured block.
12813 // longjmp() and throw() must not violate the entry/exit criteria.
12814 CS->getCapturedDecl()->setNothrow();
12815 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
12816 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12818 // 1.2.2 OpenMP Language Terminology
12819 // Structured block - An executable statement with a single entry at the
12820 // top and a single exit at the bottom.
12821 // The point of exit cannot be a branch out of the structured block.
12822 // longjmp() and throw() must not violate the entry/exit criteria.
12823 CS->getCapturedDecl()->setNothrow();
12824 }
12825
12826 // OpenMP [2.16, Nesting of Regions]
12827 // If specified, a teams construct must be contained within a target
12828 // construct. That target construct must contain no statements or directives
12829 // outside of the teams construct.
12830 if (DSAStack->hasInnerTeamsRegion()) {
12831 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12832 bool OMPTeamsFound = true;
12833 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12834 auto I = CS->body_begin();
12835 while (I != CS->body_end()) {
12836 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12837 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
12838 OMPTeamsFound) {
12839
12840 OMPTeamsFound = false;
12841 break;
12842 }
12843 ++I;
12844 }
12845 assert(I != CS->body_end() && "Not found statement");
12846 S = *I;
12847 } else {
12848 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12849 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12850 }
12851 if (!OMPTeamsFound) {
12852 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12853 Diag(DSAStack->getInnerTeamsRegionLoc(),
12854 diag::note_omp_nested_teams_construct_here);
12855 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12857 return StmtError();
12858 }
12859 }
12860
12862
12863 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
12864}
12865
12868 Stmt *AStmt, SourceLocation StartLoc,
12869 SourceLocation EndLoc) {
12870 if (!AStmt)
12871 return StmtError();
12872
12873 auto *CS = cast<CapturedStmt>(AStmt);
12874 // 1.2.2 OpenMP Language Terminology
12875 // Structured block - An executable statement with a single entry at the
12876 // top and a single exit at the bottom.
12877 // The point of exit cannot be a branch out of the structured block.
12878 // longjmp() and throw() must not violate the entry/exit criteria.
12879 CS->getCapturedDecl()->setNothrow();
12880 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
12881 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12883 // 1.2.2 OpenMP Language Terminology
12884 // Structured block - An executable statement with a single entry at the
12885 // top and a single exit at the bottom.
12886 // The point of exit cannot be a branch out of the structured block.
12887 // longjmp() and throw() must not violate the entry/exit criteria.
12888 CS->getCapturedDecl()->setNothrow();
12889 }
12890
12892
12894 Context, StartLoc, EndLoc, Clauses, AStmt,
12895 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12896}
12897
12899 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12900 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12901 if (!AStmt)
12902 return StmtError();
12903
12904 auto *CS = cast<CapturedStmt>(AStmt);
12905 // 1.2.2 OpenMP Language Terminology
12906 // Structured block - An executable statement with a single entry at the
12907 // top and a single exit at the bottom.
12908 // The point of exit cannot be a branch out of the structured block.
12909 // longjmp() and throw() must not violate the entry/exit criteria.
12910 CS->getCapturedDecl()->setNothrow();
12911 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
12912 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12914 // 1.2.2 OpenMP Language Terminology
12915 // Structured block - An executable statement with a single entry at the
12916 // top and a single exit at the bottom.
12917 // The point of exit cannot be a branch out of the structured block.
12918 // longjmp() and throw() must not violate the entry/exit criteria.
12919 CS->getCapturedDecl()->setNothrow();
12920 }
12921
12922 OMPLoopBasedDirective::HelperExprs B;
12923 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12924 // define the nested loops number.
12925 unsigned NestedLoopCount =
12926 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
12927 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
12928 VarsWithImplicitDSA, B);
12929 if (NestedLoopCount == 0)
12930 return StmtError();
12931
12932 assert((CurContext->isDependentContext() || B.builtAll()) &&
12933 "omp target parallel for loop exprs were not built");
12934
12936 // Finalize the clauses that need pre-built expressions for CodeGen.
12937 for (OMPClause *C : Clauses) {
12938 if (auto *LC = dyn_cast<OMPLinearClause>(C))
12939 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
12940 B.NumIterations, *this, CurScope,
12941 DSAStack))
12942 return StmtError();
12943 }
12944 }
12945
12948 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12949 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12950}
12951
12952/// Check for existence of a map clause in the list of clauses.
12954 const OpenMPClauseKind K) {
12955 return llvm::any_of(
12956 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
12957}
12958
12959template <typename... Params>
12961 const Params... ClauseTypes) {
12962 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
12963}
12964
12965/// Check if the variables in the mapping clause are externally visible.
12967 for (const OMPClause *C : Clauses) {
12968 if (auto *TC = dyn_cast<OMPToClause>(C))
12969 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
12970 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12971 (VD->isExternallyVisible() &&
12972 VD->getVisibility() != HiddenVisibility);
12973 });
12974 else if (auto *FC = dyn_cast<OMPFromClause>(C))
12975 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
12976 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12977 (VD->isExternallyVisible() &&
12978 VD->getVisibility() != HiddenVisibility);
12979 });
12980 }
12981
12982 return true;
12983}
12984
12986 Stmt *AStmt,
12987 SourceLocation StartLoc,
12988 SourceLocation EndLoc) {
12989 if (!AStmt)
12990 return StmtError();
12991
12992 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12993
12994 // OpenMP [2.12.2, target data Construct, Restrictions]
12995 // At least one map, use_device_addr or use_device_ptr clause must appear on
12996 // the directive.
12997 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
12998 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
12999 StringRef Expected;
13000 if (LangOpts.OpenMP < 50)
13001 Expected = "'map' or 'use_device_ptr'";
13002 else
13003 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13004 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13005 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13006 return StmtError();
13007 }
13008
13010
13011 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13012 AStmt);
13013}
13014
13017 SourceLocation StartLoc,
13018 SourceLocation EndLoc, Stmt *AStmt) {
13019 if (!AStmt)
13020 return StmtError();
13021
13022 auto *CS = cast<CapturedStmt>(AStmt);
13023 // 1.2.2 OpenMP Language Terminology
13024 // Structured block - An executable statement with a single entry at the
13025 // top and a single exit at the bottom.
13026 // The point of exit cannot be a branch out of the structured block.
13027 // longjmp() and throw() must not violate the entry/exit criteria.
13028 CS->getCapturedDecl()->setNothrow();
13029 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13030 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13032 // 1.2.2 OpenMP Language Terminology
13033 // Structured block - An executable statement with a single entry at the
13034 // top and a single exit at the bottom.
13035 // The point of exit cannot be a branch out of the structured block.
13036 // longjmp() and throw() must not violate the entry/exit criteria.
13037 CS->getCapturedDecl()->setNothrow();
13038 }
13039
13040 // OpenMP [2.10.2, Restrictions, p. 99]
13041 // At least one map clause must appear on the directive.
13042 if (!hasClauses(Clauses, OMPC_map)) {
13043 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13044 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13045 return StmtError();
13046 }
13047
13048 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13049 AStmt);
13050}
13051
13054 SourceLocation StartLoc,
13055 SourceLocation EndLoc, Stmt *AStmt) {
13056 if (!AStmt)
13057 return StmtError();
13058
13059 auto *CS = cast<CapturedStmt>(AStmt);
13060 // 1.2.2 OpenMP Language Terminology
13061 // Structured block - An executable statement with a single entry at the
13062 // top and a single exit at the bottom.
13063 // The point of exit cannot be a branch out of the structured block.
13064 // longjmp() and throw() must not violate the entry/exit criteria.
13065 CS->getCapturedDecl()->setNothrow();
13066 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13067 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13069 // 1.2.2 OpenMP Language Terminology
13070 // Structured block - An executable statement with a single entry at the
13071 // top and a single exit at the bottom.
13072 // The point of exit cannot be a branch out of the structured block.
13073 // longjmp() and throw() must not violate the entry/exit criteria.
13074 CS->getCapturedDecl()->setNothrow();
13075 }
13076
13077 // OpenMP [2.10.3, Restrictions, p. 102]
13078 // At least one map clause must appear on the directive.
13079 if (!hasClauses(Clauses, OMPC_map)) {
13080 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13081 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13082 return StmtError();
13083 }
13084
13085 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13086 AStmt);
13087}
13088
13090 SourceLocation StartLoc,
13091 SourceLocation EndLoc,
13092 Stmt *AStmt) {
13093 if (!AStmt)
13094 return StmtError();
13095
13096 auto *CS = cast<CapturedStmt>(AStmt);
13097 // 1.2.2 OpenMP Language Terminology
13098 // Structured block - An executable statement with a single entry at the
13099 // top and a single exit at the bottom.
13100 // The point of exit cannot be a branch out of the structured block.
13101 // longjmp() and throw() must not violate the entry/exit criteria.
13102 CS->getCapturedDecl()->setNothrow();
13103 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13104 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13106 // 1.2.2 OpenMP Language Terminology
13107 // Structured block - An executable statement with a single entry at the
13108 // top and a single exit at the bottom.
13109 // The point of exit cannot be a branch out of the structured block.
13110 // longjmp() and throw() must not violate the entry/exit criteria.
13111 CS->getCapturedDecl()->setNothrow();
13112 }
13113
13114 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13115 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13116 return StmtError();
13117 }
13118
13119 if (!isClauseMappable(Clauses)) {
13120 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13121 return StmtError();
13122 }
13123
13124 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13125 AStmt);
13126}
13127
13129 Stmt *AStmt, SourceLocation StartLoc,
13130 SourceLocation EndLoc) {
13131 if (!AStmt)
13132 return StmtError();
13133
13134 auto *CS = cast<CapturedStmt>(AStmt);
13135 // 1.2.2 OpenMP Language Terminology
13136 // Structured block - An executable statement with a single entry at the
13137 // top and a single exit at the bottom.
13138 // The point of exit cannot be a branch out of the structured block.
13139 // longjmp() and throw() must not violate the entry/exit criteria.
13140 CS->getCapturedDecl()->setNothrow();
13141
13143
13144 DSAStack->setParentTeamsRegionLoc(StartLoc);
13145
13146 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13147}
13148
13151 SourceLocation EndLoc,
13152 OpenMPDirectiveKind CancelRegion) {
13153 if (DSAStack->isParentNowaitRegion()) {
13154 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13155 return StmtError();
13156 }
13157 if (DSAStack->isParentOrderedRegion()) {
13158 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13159 return StmtError();
13160 }
13161 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13162 CancelRegion);
13163}
13164
13166 SourceLocation StartLoc,
13167 SourceLocation EndLoc,
13168 OpenMPDirectiveKind CancelRegion) {
13169 if (DSAStack->isParentNowaitRegion()) {
13170 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13171 return StmtError();
13172 }
13173 if (DSAStack->isParentOrderedRegion()) {
13174 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13175 return StmtError();
13176 }
13177 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13178 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13179 CancelRegion);
13180}
13181
13183 ArrayRef<OMPClause *> Clauses) {
13184 const OMPClause *ReductionClause = nullptr;
13185 const OMPClause *NogroupClause = nullptr;
13186 for (const OMPClause *C : Clauses) {
13187 if (C->getClauseKind() == OMPC_reduction) {
13188 ReductionClause = C;
13189 if (NogroupClause)
13190 break;
13191 continue;
13192 }
13193 if (C->getClauseKind() == OMPC_nogroup) {
13194 NogroupClause = C;
13195 if (ReductionClause)
13196 break;
13197 continue;
13198 }
13199 }
13200 if (ReductionClause && NogroupClause) {
13201 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13202 << SourceRange(NogroupClause->getBeginLoc(),
13203 NogroupClause->getEndLoc());
13204 return true;
13205 }
13206 return false;
13207}
13208
13210 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13211 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13212 if (!AStmt)
13213 return StmtError();
13214
13215 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13216 OMPLoopBasedDirective::HelperExprs B;
13217 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13218 // define the nested loops number.
13219 unsigned NestedLoopCount =
13220 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13221 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13222 VarsWithImplicitDSA, B);
13223 if (NestedLoopCount == 0)
13224 return StmtError();
13225
13226 assert((CurContext->isDependentContext() || B.builtAll()) &&
13227 "omp for loop exprs were not built");
13228
13229 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13230 // The grainsize clause and num_tasks clause are mutually exclusive and may
13231 // not appear on the same taskloop directive.
13232 if (checkMutuallyExclusiveClauses(*this, Clauses,
13233 {OMPC_grainsize, OMPC_num_tasks}))
13234 return StmtError();
13235 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13236 // If a reduction clause is present on the taskloop directive, the nogroup
13237 // clause must not be specified.
13238 if (checkReductionClauseWithNogroup(*this, Clauses))
13239 return StmtError();
13240
13242 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13243 NestedLoopCount, Clauses, AStmt, B,
13244 DSAStack->isCancelRegion());
13245}
13246
13248 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13249 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13250 if (!AStmt)
13251 return StmtError();
13252
13253 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13254 OMPLoopBasedDirective::HelperExprs B;
13255 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13256 // define the nested loops number.
13257 unsigned NestedLoopCount =
13258 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13259 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13260 VarsWithImplicitDSA, B);
13261 if (NestedLoopCount == 0)
13262 return StmtError();
13263
13264 assert((CurContext->isDependentContext() || B.builtAll()) &&
13265 "omp for loop exprs were not built");
13266
13268 // Finalize the clauses that need pre-built expressions for CodeGen.
13269 for (OMPClause *C : Clauses) {
13270 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13271 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13272 B.NumIterations, *this, CurScope,
13273 DSAStack))
13274 return StmtError();
13275 }
13276 }
13277
13278 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13279 // The grainsize clause and num_tasks clause are mutually exclusive and may
13280 // not appear on the same taskloop directive.
13281 if (checkMutuallyExclusiveClauses(*this, Clauses,
13282 {OMPC_grainsize, OMPC_num_tasks}))
13283 return StmtError();
13284 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13285 // If a reduction clause is present on the taskloop directive, the nogroup
13286 // clause must not be specified.
13287 if (checkReductionClauseWithNogroup(*this, Clauses))
13288 return StmtError();
13289 if (checkSimdlenSafelenSpecified(*this, Clauses))
13290 return StmtError();
13291
13293 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13294 NestedLoopCount, Clauses, AStmt, B);
13295}
13296
13298 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13299 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13300 if (!AStmt)
13301 return StmtError();
13302
13303 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13304 OMPLoopBasedDirective::HelperExprs B;
13305 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13306 // define the nested loops number.
13307 unsigned NestedLoopCount =
13308 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13309 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13310 VarsWithImplicitDSA, B);
13311 if (NestedLoopCount == 0)
13312 return StmtError();
13313
13314 assert((CurContext->isDependentContext() || B.builtAll()) &&
13315 "omp for loop exprs were not built");
13316
13317 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13318 // The grainsize clause and num_tasks clause are mutually exclusive and may
13319 // not appear on the same taskloop directive.
13320 if (checkMutuallyExclusiveClauses(*this, Clauses,
13321 {OMPC_grainsize, OMPC_num_tasks}))
13322 return StmtError();
13323 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13324 // If a reduction clause is present on the taskloop directive, the nogroup
13325 // clause must not be specified.
13326 if (checkReductionClauseWithNogroup(*this, Clauses))
13327 return StmtError();
13328
13330 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13331 NestedLoopCount, Clauses, AStmt, B,
13332 DSAStack->isCancelRegion());
13333}
13334
13336 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13337 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13338 if (!AStmt)
13339 return StmtError();
13340
13341 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13342 OMPLoopBasedDirective::HelperExprs B;
13343 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13344 // define the nested loops number.
13345 unsigned NestedLoopCount =
13346 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13347 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13348 VarsWithImplicitDSA, B);
13349 if (NestedLoopCount == 0)
13350 return StmtError();
13351
13352 assert((CurContext->isDependentContext() || B.builtAll()) &&
13353 "omp for loop exprs were not built");
13354
13355 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13356 // The grainsize clause and num_tasks clause are mutually exclusive and may
13357 // not appear on the same taskloop directive.
13358 if (checkMutuallyExclusiveClauses(*this, Clauses,
13359 {OMPC_grainsize, OMPC_num_tasks}))
13360 return StmtError();
13361 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13362 // If a reduction clause is present on the taskloop directive, the nogroup
13363 // clause must not be specified.
13364 if (checkReductionClauseWithNogroup(*this, Clauses))
13365 return StmtError();
13366
13368 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13369 NestedLoopCount, Clauses, AStmt, B,
13370 DSAStack->isCancelRegion());
13371}
13372
13374 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13375 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13376 if (!AStmt)
13377 return StmtError();
13378
13379 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13380 OMPLoopBasedDirective::HelperExprs B;
13381 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13382 // define the nested loops number.
13383 unsigned NestedLoopCount =
13384 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13385 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13386 VarsWithImplicitDSA, B);
13387 if (NestedLoopCount == 0)
13388 return StmtError();
13389
13390 assert((CurContext->isDependentContext() || B.builtAll()) &&
13391 "omp for loop exprs were not built");
13392
13394 // Finalize the clauses that need pre-built expressions for CodeGen.
13395 for (OMPClause *C : Clauses) {
13396 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13397 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13398 B.NumIterations, *this, CurScope,
13399 DSAStack))
13400 return StmtError();
13401 }
13402 }
13403
13404 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13405 // The grainsize clause and num_tasks clause are mutually exclusive and may
13406 // not appear on the same taskloop directive.
13407 if (checkMutuallyExclusiveClauses(*this, Clauses,
13408 {OMPC_grainsize, OMPC_num_tasks}))
13409 return StmtError();
13410 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13411 // If a reduction clause is present on the taskloop directive, the nogroup
13412 // clause must not be specified.
13413 if (checkReductionClauseWithNogroup(*this, Clauses))
13414 return StmtError();
13415 if (checkSimdlenSafelenSpecified(*this, Clauses))
13416 return StmtError();
13417
13420 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13421}
13422
13424 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13425 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13426 if (!AStmt)
13427 return StmtError();
13428
13429 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13430 OMPLoopBasedDirective::HelperExprs B;
13431 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13432 // define the nested loops number.
13433 unsigned NestedLoopCount =
13434 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13435 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13436 VarsWithImplicitDSA, B);
13437 if (NestedLoopCount == 0)
13438 return StmtError();
13439
13440 assert((CurContext->isDependentContext() || B.builtAll()) &&
13441 "omp for loop exprs were not built");
13442
13444 // Finalize the clauses that need pre-built expressions for CodeGen.
13445 for (OMPClause *C : Clauses) {
13446 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13447 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13448 B.NumIterations, *this, CurScope,
13449 DSAStack))
13450 return StmtError();
13451 }
13452 }
13453
13454 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13455 // The grainsize clause and num_tasks clause are mutually exclusive and may
13456 // not appear on the same taskloop directive.
13457 if (checkMutuallyExclusiveClauses(*this, Clauses,
13458 {OMPC_grainsize, OMPC_num_tasks}))
13459 return StmtError();
13460 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13461 // If a reduction clause is present on the taskloop directive, the nogroup
13462 // clause must not be specified.
13463 if (checkReductionClauseWithNogroup(*this, Clauses))
13464 return StmtError();
13465 if (checkSimdlenSafelenSpecified(*this, Clauses))
13466 return StmtError();
13467
13470 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13471}
13472
13474 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13475 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13476 if (!AStmt)
13477 return StmtError();
13478
13479 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13480 auto *CS = cast<CapturedStmt>(AStmt);
13481 // 1.2.2 OpenMP Language Terminology
13482 // Structured block - An executable statement with a single entry at the
13483 // top and a single exit at the bottom.
13484 // The point of exit cannot be a branch out of the structured block.
13485 // longjmp() and throw() must not violate the entry/exit criteria.
13486 CS->getCapturedDecl()->setNothrow();
13487 for (int ThisCaptureLevel =
13488 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13489 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13491 // 1.2.2 OpenMP Language Terminology
13492 // Structured block - An executable statement with a single entry at the
13493 // top and a single exit at the bottom.
13494 // The point of exit cannot be a branch out of the structured block.
13495 // longjmp() and throw() must not violate the entry/exit criteria.
13496 CS->getCapturedDecl()->setNothrow();
13497 }
13498
13499 OMPLoopBasedDirective::HelperExprs B;
13500 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13501 // define the nested loops number.
13502 unsigned NestedLoopCount = checkOpenMPLoop(
13503 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13504 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13505 VarsWithImplicitDSA, B);
13506 if (NestedLoopCount == 0)
13507 return StmtError();
13508
13509 assert((CurContext->isDependentContext() || B.builtAll()) &&
13510 "omp for loop exprs were not built");
13511
13512 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13513 // The grainsize clause and num_tasks clause are mutually exclusive and may
13514 // not appear on the same taskloop directive.
13515 if (checkMutuallyExclusiveClauses(*this, Clauses,
13516 {OMPC_grainsize, OMPC_num_tasks}))
13517 return StmtError();
13518 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13519 // If a reduction clause is present on the taskloop directive, the nogroup
13520 // clause must not be specified.
13521 if (checkReductionClauseWithNogroup(*this, Clauses))
13522 return StmtError();
13523
13526 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13527 DSAStack->isCancelRegion());
13528}
13529
13531 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13532 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13533 if (!AStmt)
13534 return StmtError();
13535
13536 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13537 auto *CS = cast<CapturedStmt>(AStmt);
13538 // 1.2.2 OpenMP Language Terminology
13539 // Structured block - An executable statement with a single entry at the
13540 // top and a single exit at the bottom.
13541 // The point of exit cannot be a branch out of the structured block.
13542 // longjmp() and throw() must not violate the entry/exit criteria.
13543 CS->getCapturedDecl()->setNothrow();
13544 for (int ThisCaptureLevel =
13545 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13546 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13548 // 1.2.2 OpenMP Language Terminology
13549 // Structured block - An executable statement with a single entry at the
13550 // top and a single exit at the bottom.
13551 // The point of exit cannot be a branch out of the structured block.
13552 // longjmp() and throw() must not violate the entry/exit criteria.
13553 CS->getCapturedDecl()->setNothrow();
13554 }
13555
13556 OMPLoopBasedDirective::HelperExprs B;
13557 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13558 // define the nested loops number.
13559 unsigned NestedLoopCount = checkOpenMPLoop(
13560 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13561 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13562 VarsWithImplicitDSA, B);
13563 if (NestedLoopCount == 0)
13564 return StmtError();
13565
13566 assert((CurContext->isDependentContext() || B.builtAll()) &&
13567 "omp for loop exprs were not built");
13568
13569 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13570 // The grainsize clause and num_tasks clause are mutually exclusive and may
13571 // not appear on the same taskloop directive.
13572 if (checkMutuallyExclusiveClauses(*this, Clauses,
13573 {OMPC_grainsize, OMPC_num_tasks}))
13574 return StmtError();
13575 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13576 // If a reduction clause is present on the taskloop directive, the nogroup
13577 // clause must not be specified.
13578 if (checkReductionClauseWithNogroup(*this, Clauses))
13579 return StmtError();
13580
13583 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13584 DSAStack->isCancelRegion());
13585}
13586
13588 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13589 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13590 if (!AStmt)
13591 return StmtError();
13592
13593 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13594 auto *CS = cast<CapturedStmt>(AStmt);
13595 // 1.2.2 OpenMP Language Terminology
13596 // Structured block - An executable statement with a single entry at the
13597 // top and a single exit at the bottom.
13598 // The point of exit cannot be a branch out of the structured block.
13599 // longjmp() and throw() must not violate the entry/exit criteria.
13600 CS->getCapturedDecl()->setNothrow();
13601 for (int ThisCaptureLevel =
13602 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
13603 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13605 // 1.2.2 OpenMP Language Terminology
13606 // Structured block - An executable statement with a single entry at the
13607 // top and a single exit at the bottom.
13608 // The point of exit cannot be a branch out of the structured block.
13609 // longjmp() and throw() must not violate the entry/exit criteria.
13610 CS->getCapturedDecl()->setNothrow();
13611 }
13612
13613 OMPLoopBasedDirective::HelperExprs B;
13614 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13615 // define the nested loops number.
13616 unsigned NestedLoopCount = checkOpenMPLoop(
13617 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13618 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13619 VarsWithImplicitDSA, B);
13620 if (NestedLoopCount == 0)
13621 return StmtError();
13622
13623 assert((CurContext->isDependentContext() || B.builtAll()) &&
13624 "omp for loop exprs were not built");
13625
13627 // Finalize the clauses that need pre-built expressions for CodeGen.
13628 for (OMPClause *C : Clauses) {
13629 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13630 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13631 B.NumIterations, *this, CurScope,
13632 DSAStack))
13633 return StmtError();
13634 }
13635 }
13636
13637 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13638 // The grainsize clause and num_tasks clause are mutually exclusive and may
13639 // not appear on the same taskloop directive.
13640 if (checkMutuallyExclusiveClauses(*this, Clauses,
13641 {OMPC_grainsize, OMPC_num_tasks}))
13642 return StmtError();
13643 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13644 // If a reduction clause is present on the taskloop directive, the nogroup
13645 // clause must not be specified.
13646 if (checkReductionClauseWithNogroup(*this, Clauses))
13647 return StmtError();
13648 if (checkSimdlenSafelenSpecified(*this, Clauses))
13649 return StmtError();
13650
13653 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13654}
13655
13657 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13658 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13659 if (!AStmt)
13660 return StmtError();
13661
13662 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13663 auto *CS = cast<CapturedStmt>(AStmt);
13664 // 1.2.2 OpenMP Language Terminology
13665 // Structured block - An executable statement with a single entry at the
13666 // top and a single exit at the bottom.
13667 // The point of exit cannot be a branch out of the structured block.
13668 // longjmp() and throw() must not violate the entry/exit criteria.
13669 CS->getCapturedDecl()->setNothrow();
13670 for (int ThisCaptureLevel =
13671 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
13672 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13674 // 1.2.2 OpenMP Language Terminology
13675 // Structured block - An executable statement with a single entry at the
13676 // top and a single exit at the bottom.
13677 // The point of exit cannot be a branch out of the structured block.
13678 // longjmp() and throw() must not violate the entry/exit criteria.
13679 CS->getCapturedDecl()->setNothrow();
13680 }
13681
13682 OMPLoopBasedDirective::HelperExprs B;
13683 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13684 // define the nested loops number.
13685 unsigned NestedLoopCount = checkOpenMPLoop(
13686 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13687 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13688 VarsWithImplicitDSA, B);
13689 if (NestedLoopCount == 0)
13690 return StmtError();
13691
13692 assert((CurContext->isDependentContext() || B.builtAll()) &&
13693 "omp for loop exprs were not built");
13694
13696 // Finalize the clauses that need pre-built expressions for CodeGen.
13697 for (OMPClause *C : Clauses) {
13698 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13699 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13700 B.NumIterations, *this, CurScope,
13701 DSAStack))
13702 return StmtError();
13703 }
13704 }
13705
13706 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13707 // The grainsize clause and num_tasks clause are mutually exclusive and may
13708 // not appear on the same taskloop directive.
13709 if (checkMutuallyExclusiveClauses(*this, Clauses,
13710 {OMPC_grainsize, OMPC_num_tasks}))
13711 return StmtError();
13712 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13713 // If a reduction clause is present on the taskloop directive, the nogroup
13714 // clause must not be specified.
13715 if (checkReductionClauseWithNogroup(*this, Clauses))
13716 return StmtError();
13717 if (checkSimdlenSafelenSpecified(*this, Clauses))
13718 return StmtError();
13719
13722 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13723}
13724
13726 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13727 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13728 if (!AStmt)
13729 return StmtError();
13730
13731 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13732 OMPLoopBasedDirective::HelperExprs B;
13733 // In presence of clause 'collapse' with number of loops, it will
13734 // define the nested loops number.
13735 unsigned NestedLoopCount =
13736 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13737 nullptr /*ordered not a clause on distribute*/, AStmt,
13738 *this, *DSAStack, VarsWithImplicitDSA, B);
13739 if (NestedLoopCount == 0)
13740 return StmtError();
13741
13742 assert((CurContext->isDependentContext() || B.builtAll()) &&
13743 "omp for loop exprs were not built");
13744
13746 return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
13747 NestedLoopCount, Clauses, AStmt, B);
13748}
13749
13751 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13752 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13753 if (!AStmt)
13754 return StmtError();
13755
13756 auto *CS = cast<CapturedStmt>(AStmt);
13757 // 1.2.2 OpenMP Language Terminology
13758 // Structured block - An executable statement with a single entry at the
13759 // top and a single exit at the bottom.
13760 // The point of exit cannot be a branch out of the structured block.
13761 // longjmp() and throw() must not violate the entry/exit criteria.
13762 CS->getCapturedDecl()->setNothrow();
13763 for (int ThisCaptureLevel =
13764 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
13765 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13767 // 1.2.2 OpenMP Language Terminology
13768 // Structured block - An executable statement with a single entry at the
13769 // top and a single exit at the bottom.
13770 // The point of exit cannot be a branch out of the structured block.
13771 // longjmp() and throw() must not violate the entry/exit criteria.
13772 CS->getCapturedDecl()->setNothrow();
13773 }
13774
13775 OMPLoopBasedDirective::HelperExprs B;
13776 // In presence of clause 'collapse' with number of loops, it will
13777 // define the nested loops number.
13778 unsigned NestedLoopCount = checkOpenMPLoop(
13779 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13780 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
13781 VarsWithImplicitDSA, B);
13782 if (NestedLoopCount == 0)
13783 return StmtError();
13784
13785 assert((CurContext->isDependentContext() || B.builtAll()) &&
13786 "omp for loop exprs were not built");
13787
13790 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13791 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13792}
13793
13795 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13796 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13797 if (!AStmt)
13798 return StmtError();
13799
13800 auto *CS = cast<CapturedStmt>(AStmt);
13801 // 1.2.2 OpenMP Language Terminology
13802 // Structured block - An executable statement with a single entry at the
13803 // top and a single exit at the bottom.
13804 // The point of exit cannot be a branch out of the structured block.
13805 // longjmp() and throw() must not violate the entry/exit criteria.
13806 CS->getCapturedDecl()->setNothrow();
13807 for (int ThisCaptureLevel =
13808 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
13809 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13811 // 1.2.2 OpenMP Language Terminology
13812 // Structured block - An executable statement with a single entry at the
13813 // top and a single exit at the bottom.
13814 // The point of exit cannot be a branch out of the structured block.
13815 // longjmp() and throw() must not violate the entry/exit criteria.
13816 CS->getCapturedDecl()->setNothrow();
13817 }
13818
13819 OMPLoopBasedDirective::HelperExprs B;
13820 // In presence of clause 'collapse' with number of loops, it will
13821 // define the nested loops number.
13822 unsigned NestedLoopCount = checkOpenMPLoop(
13823 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13824 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
13825 VarsWithImplicitDSA, B);
13826 if (NestedLoopCount == 0)
13827 return StmtError();
13828
13829 assert((CurContext->isDependentContext() || B.builtAll()) &&
13830 "omp for loop exprs were not built");
13831
13833 // Finalize the clauses that need pre-built expressions for CodeGen.
13834 for (OMPClause *C : Clauses) {
13835 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13836 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13837 B.NumIterations, *this, CurScope,
13838 DSAStack))
13839 return StmtError();
13840 }
13841 }
13842
13843 if (checkSimdlenSafelenSpecified(*this, Clauses))
13844 return StmtError();
13845
13848 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13849}
13850
13852 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13853 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13854 if (!AStmt)
13855 return StmtError();
13856
13857 auto *CS = cast<CapturedStmt>(AStmt);
13858 // 1.2.2 OpenMP Language Terminology
13859 // Structured block - An executable statement with a single entry at the
13860 // top and a single exit at the bottom.
13861 // The point of exit cannot be a branch out of the structured block.
13862 // longjmp() and throw() must not violate the entry/exit criteria.
13863 CS->getCapturedDecl()->setNothrow();
13864 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
13865 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13867 // 1.2.2 OpenMP Language Terminology
13868 // Structured block - An executable statement with a single entry at the
13869 // top and a single exit at the bottom.
13870 // The point of exit cannot be a branch out of the structured block.
13871 // longjmp() and throw() must not violate the entry/exit criteria.
13872 CS->getCapturedDecl()->setNothrow();
13873 }
13874
13875 OMPLoopBasedDirective::HelperExprs B;
13876 // In presence of clause 'collapse' with number of loops, it will
13877 // define the nested loops number.
13878 unsigned NestedLoopCount =
13879 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13880 nullptr /*ordered not a clause on distribute*/, CS, *this,
13881 *DSAStack, VarsWithImplicitDSA, B);
13882 if (NestedLoopCount == 0)
13883 return StmtError();
13884
13885 assert((CurContext->isDependentContext() || B.builtAll()) &&
13886 "omp for loop exprs were not built");
13887
13889 // Finalize the clauses that need pre-built expressions for CodeGen.
13890 for (OMPClause *C : Clauses) {
13891 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13892 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13893 B.NumIterations, *this, CurScope,
13894 DSAStack))
13895 return StmtError();
13896 }
13897 }
13898
13899 if (checkSimdlenSafelenSpecified(*this, Clauses))
13900 return StmtError();
13901
13903 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
13904 NestedLoopCount, Clauses, AStmt, B);
13905}
13906
13908 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13909 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13910 if (!AStmt)
13911 return StmtError();
13912
13913 auto *CS = cast<CapturedStmt>(AStmt);
13914 // 1.2.2 OpenMP Language Terminology
13915 // Structured block - An executable statement with a single entry at the
13916 // top and a single exit at the bottom.
13917 // The point of exit cannot be a branch out of the structured block.
13918 // longjmp() and throw() must not violate the entry/exit criteria.
13919 CS->getCapturedDecl()->setNothrow();
13920 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13921 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13923 // 1.2.2 OpenMP Language Terminology
13924 // Structured block - An executable statement with a single entry at the
13925 // top and a single exit at the bottom.
13926 // The point of exit cannot be a branch out of the structured block.
13927 // longjmp() and throw() must not violate the entry/exit criteria.
13928 CS->getCapturedDecl()->setNothrow();
13929 }
13930
13931 OMPLoopBasedDirective::HelperExprs B;
13932 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13933 // define the nested loops number.
13934 unsigned NestedLoopCount = checkOpenMPLoop(
13935 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13936 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
13937 B);
13938 if (NestedLoopCount == 0)
13939 return StmtError();
13940
13941 assert((CurContext->isDependentContext() || B.builtAll()) &&
13942 "omp target parallel for simd loop exprs were not built");
13943
13945 // Finalize the clauses that need pre-built expressions for CodeGen.
13946 for (OMPClause *C : Clauses) {
13947 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13948 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13949 B.NumIterations, *this, CurScope,
13950 DSAStack))
13951 return StmtError();
13952 }
13953 }
13954 if (checkSimdlenSafelenSpecified(*this, Clauses))
13955 return StmtError();
13956
13959 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13960}
13961
13963 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13964 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13965 if (!AStmt)
13966 return StmtError();
13967
13968 auto *CS = cast<CapturedStmt>(AStmt);
13969 // 1.2.2 OpenMP Language Terminology
13970 // Structured block - An executable statement with a single entry at the
13971 // top and a single exit at the bottom.
13972 // The point of exit cannot be a branch out of the structured block.
13973 // longjmp() and throw() must not violate the entry/exit criteria.
13974 CS->getCapturedDecl()->setNothrow();
13975 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
13976 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13978 // 1.2.2 OpenMP Language Terminology
13979 // Structured block - An executable statement with a single entry at the
13980 // top and a single exit at the bottom.
13981 // The point of exit cannot be a branch out of the structured block.
13982 // longjmp() and throw() must not violate the entry/exit criteria.
13983 CS->getCapturedDecl()->setNothrow();
13984 }
13985
13986 OMPLoopBasedDirective::HelperExprs B;
13987 // In presence of clause 'collapse' with number of loops, it will define the
13988 // nested loops number.
13989 unsigned NestedLoopCount =
13990 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13991 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13992 VarsWithImplicitDSA, B);
13993 if (NestedLoopCount == 0)
13994 return StmtError();
13995
13996 assert((CurContext->isDependentContext() || B.builtAll()) &&
13997 "omp target simd loop exprs were not built");
13998
14000 // Finalize the clauses that need pre-built expressions for CodeGen.
14001 for (OMPClause *C : Clauses) {
14002 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14003 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14004 B.NumIterations, *this, CurScope,
14005 DSAStack))
14006 return StmtError();
14007 }
14008 }
14009
14010 if (checkSimdlenSafelenSpecified(*this, Clauses))
14011 return StmtError();
14012
14014 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14015 NestedLoopCount, Clauses, AStmt, B);
14016}
14017
14019 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14020 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14021 if (!AStmt)
14022 return StmtError();
14023
14024 auto *CS = cast<CapturedStmt>(AStmt);
14025 // 1.2.2 OpenMP Language Terminology
14026 // Structured block - An executable statement with a single entry at the
14027 // top and a single exit at the bottom.
14028 // The point of exit cannot be a branch out of the structured block.
14029 // longjmp() and throw() must not violate the entry/exit criteria.
14030 CS->getCapturedDecl()->setNothrow();
14031 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14032 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14034 // 1.2.2 OpenMP Language Terminology
14035 // Structured block - An executable statement with a single entry at the
14036 // top and a single exit at the bottom.
14037 // The point of exit cannot be a branch out of the structured block.
14038 // longjmp() and throw() must not violate the entry/exit criteria.
14039 CS->getCapturedDecl()->setNothrow();
14040 }
14041
14042 OMPLoopBasedDirective::HelperExprs B;
14043 // In presence of clause 'collapse' with number of loops, it will
14044 // define the nested loops number.
14045 unsigned NestedLoopCount =
14046 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14047 nullptr /*ordered not a clause on distribute*/, CS, *this,
14048 *DSAStack, VarsWithImplicitDSA, B);
14049 if (NestedLoopCount == 0)
14050 return StmtError();
14051
14052 assert((CurContext->isDependentContext() || B.builtAll()) &&
14053 "omp teams distribute loop exprs were not built");
14054
14056
14057 DSAStack->setParentTeamsRegionLoc(StartLoc);
14058
14060 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14061}
14062
14064 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14065 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14066 if (!AStmt)
14067 return StmtError();
14068
14069 auto *CS = cast<CapturedStmt>(AStmt);
14070 // 1.2.2 OpenMP Language Terminology
14071 // Structured block - An executable statement with a single entry at the
14072 // top and a single exit at the bottom.
14073 // The point of exit cannot be a branch out of the structured block.
14074 // longjmp() and throw() must not violate the entry/exit criteria.
14075 CS->getCapturedDecl()->setNothrow();
14076 for (int ThisCaptureLevel =
14077 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14078 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14080 // 1.2.2 OpenMP Language Terminology
14081 // Structured block - An executable statement with a single entry at the
14082 // top and a single exit at the bottom.
14083 // The point of exit cannot be a branch out of the structured block.
14084 // longjmp() and throw() must not violate the entry/exit criteria.
14085 CS->getCapturedDecl()->setNothrow();
14086 }
14087
14088 OMPLoopBasedDirective::HelperExprs B;
14089 // In presence of clause 'collapse' with number of loops, it will
14090 // define the nested loops number.
14091 unsigned NestedLoopCount = checkOpenMPLoop(
14092 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14093 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14094 VarsWithImplicitDSA, B);
14095
14096 if (NestedLoopCount == 0)
14097 return StmtError();
14098
14099 assert((CurContext->isDependentContext() || B.builtAll()) &&
14100 "omp teams distribute simd loop exprs were not built");
14101
14103 // Finalize the clauses that need pre-built expressions for CodeGen.
14104 for (OMPClause *C : Clauses) {
14105 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14106 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14107 B.NumIterations, *this, CurScope,
14108 DSAStack))
14109 return StmtError();
14110 }
14111 }
14112
14113 if (checkSimdlenSafelenSpecified(*this, Clauses))
14114 return StmtError();
14115
14117
14118 DSAStack->setParentTeamsRegionLoc(StartLoc);
14119
14121 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14122}
14123
14125 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14126 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14127 if (!AStmt)
14128 return StmtError();
14129
14130 auto *CS = cast<CapturedStmt>(AStmt);
14131 // 1.2.2 OpenMP Language Terminology
14132 // Structured block - An executable statement with a single entry at the
14133 // top and a single exit at the bottom.
14134 // The point of exit cannot be a branch out of the structured block.
14135 // longjmp() and throw() must not violate the entry/exit criteria.
14136 CS->getCapturedDecl()->setNothrow();
14137
14138 for (int ThisCaptureLevel =
14139 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14140 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14142 // 1.2.2 OpenMP Language Terminology
14143 // Structured block - An executable statement with a single entry at the
14144 // top and a single exit at the bottom.
14145 // The point of exit cannot be a branch out of the structured block.
14146 // longjmp() and throw() must not violate the entry/exit criteria.
14147 CS->getCapturedDecl()->setNothrow();
14148 }
14149
14150 OMPLoopBasedDirective::HelperExprs B;
14151 // In presence of clause 'collapse' with number of loops, it will
14152 // define the nested loops number.
14153 unsigned NestedLoopCount = checkOpenMPLoop(
14154 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14155 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14156 VarsWithImplicitDSA, B);
14157
14158 if (NestedLoopCount == 0)
14159 return StmtError();
14160
14161 assert((CurContext->isDependentContext() || B.builtAll()) &&
14162 "omp for loop exprs were not built");
14163
14165 // Finalize the clauses that need pre-built expressions for CodeGen.
14166 for (OMPClause *C : Clauses) {
14167 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14168 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14169 B.NumIterations, *this, CurScope,
14170 DSAStack))
14171 return StmtError();
14172 }
14173 }
14174
14175 if (checkSimdlenSafelenSpecified(*this, Clauses))
14176 return StmtError();
14177
14179
14180 DSAStack->setParentTeamsRegionLoc(StartLoc);
14181
14183 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14184}
14185
14187 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14188 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14189 if (!AStmt)
14190 return StmtError();
14191
14192 auto *CS = cast<CapturedStmt>(AStmt);
14193 // 1.2.2 OpenMP Language Terminology
14194 // Structured block - An executable statement with a single entry at the
14195 // top and a single exit at the bottom.
14196 // The point of exit cannot be a branch out of the structured block.
14197 // longjmp() and throw() must not violate the entry/exit criteria.
14198 CS->getCapturedDecl()->setNothrow();
14199
14200 for (int ThisCaptureLevel =
14201 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14202 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14204 // 1.2.2 OpenMP Language Terminology
14205 // Structured block - An executable statement with a single entry at the
14206 // top and a single exit at the bottom.
14207 // The point of exit cannot be a branch out of the structured block.
14208 // longjmp() and throw() must not violate the entry/exit criteria.
14209 CS->getCapturedDecl()->setNothrow();
14210 }
14211
14212 OMPLoopBasedDirective::HelperExprs B;
14213 // In presence of clause 'collapse' with number of loops, it will
14214 // define the nested loops number.
14215 unsigned NestedLoopCount = checkOpenMPLoop(
14216 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14217 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14218 VarsWithImplicitDSA, B);
14219
14220 if (NestedLoopCount == 0)
14221 return StmtError();
14222
14223 assert((CurContext->isDependentContext() || B.builtAll()) &&
14224 "omp for loop exprs were not built");
14225
14227
14228 DSAStack->setParentTeamsRegionLoc(StartLoc);
14229
14231 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14232 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14233}
14234
14236 Stmt *AStmt,
14237 SourceLocation StartLoc,
14238 SourceLocation EndLoc) {
14239 if (!AStmt)
14240 return StmtError();
14241
14242 auto *CS = cast<CapturedStmt>(AStmt);
14243 // 1.2.2 OpenMP Language Terminology
14244 // Structured block - An executable statement with a single entry at the
14245 // top and a single exit at the bottom.
14246 // The point of exit cannot be a branch out of the structured block.
14247 // longjmp() and throw() must not violate the entry/exit criteria.
14248 CS->getCapturedDecl()->setNothrow();
14249
14250 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14251 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14253 // 1.2.2 OpenMP Language Terminology
14254 // Structured block - An executable statement with a single entry at the
14255 // top and a single exit at the bottom.
14256 // The point of exit cannot be a branch out of the structured block.
14257 // longjmp() and throw() must not violate the entry/exit criteria.
14258 CS->getCapturedDecl()->setNothrow();
14259 }
14261
14262 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14263 AStmt);
14264}
14265
14267 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14268 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14269 if (!AStmt)
14270 return StmtError();
14271
14272 auto *CS = cast<CapturedStmt>(AStmt);
14273 // 1.2.2 OpenMP Language Terminology
14274 // Structured block - An executable statement with a single entry at the
14275 // top and a single exit at the bottom.
14276 // The point of exit cannot be a branch out of the structured block.
14277 // longjmp() and throw() must not violate the entry/exit criteria.
14278 CS->getCapturedDecl()->setNothrow();
14279 for (int ThisCaptureLevel =
14280 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14281 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14283 // 1.2.2 OpenMP Language Terminology
14284 // Structured block - An executable statement with a single entry at the
14285 // top and a single exit at the bottom.
14286 // The point of exit cannot be a branch out of the structured block.
14287 // longjmp() and throw() must not violate the entry/exit criteria.
14288 CS->getCapturedDecl()->setNothrow();
14289 }
14290
14291 OMPLoopBasedDirective::HelperExprs B;
14292 // In presence of clause 'collapse' with number of loops, it will
14293 // define the nested loops number.
14294 unsigned NestedLoopCount = checkOpenMPLoop(
14295 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14296 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14297 VarsWithImplicitDSA, B);
14298 if (NestedLoopCount == 0)
14299 return StmtError();
14300
14301 assert((CurContext->isDependentContext() || B.builtAll()) &&
14302 "omp target teams distribute loop exprs were not built");
14303
14306 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14307}
14308
14310 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14311 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14312 if (!AStmt)
14313 return StmtError();
14314
14315 auto *CS = cast<CapturedStmt>(AStmt);
14316 // 1.2.2 OpenMP Language Terminology
14317 // Structured block - An executable statement with a single entry at the
14318 // top and a single exit at the bottom.
14319 // The point of exit cannot be a branch out of the structured block.
14320 // longjmp() and throw() must not violate the entry/exit criteria.
14321 CS->getCapturedDecl()->setNothrow();
14322 for (int ThisCaptureLevel =
14323 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14324 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14326 // 1.2.2 OpenMP Language Terminology
14327 // Structured block - An executable statement with a single entry at the
14328 // top and a single exit at the bottom.
14329 // The point of exit cannot be a branch out of the structured block.
14330 // longjmp() and throw() must not violate the entry/exit criteria.
14331 CS->getCapturedDecl()->setNothrow();
14332 }
14333
14334 OMPLoopBasedDirective::HelperExprs B;
14335 // In presence of clause 'collapse' with number of loops, it will
14336 // define the nested loops number.
14337 unsigned NestedLoopCount = checkOpenMPLoop(
14338 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14339 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14340 VarsWithImplicitDSA, B);
14341 if (NestedLoopCount == 0)
14342 return StmtError();
14343
14344 assert((CurContext->isDependentContext() || B.builtAll()) &&
14345 "omp target teams distribute parallel for loop exprs were not built");
14346
14348 // Finalize the clauses that need pre-built expressions for CodeGen.
14349 for (OMPClause *C : Clauses) {
14350 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14351 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14352 B.NumIterations, *this, CurScope,
14353 DSAStack))
14354 return StmtError();
14355 }
14356 }
14357
14360 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14361 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14362}
14363
14365 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14366 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14367 if (!AStmt)
14368 return StmtError();
14369
14370 auto *CS = cast<CapturedStmt>(AStmt);
14371 // 1.2.2 OpenMP Language Terminology
14372 // Structured block - An executable statement with a single entry at the
14373 // top and a single exit at the bottom.
14374 // The point of exit cannot be a branch out of the structured block.
14375 // longjmp() and throw() must not violate the entry/exit criteria.
14376 CS->getCapturedDecl()->setNothrow();
14377 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14378 OMPD_target_teams_distribute_parallel_for_simd);
14379 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14381 // 1.2.2 OpenMP Language Terminology
14382 // Structured block - An executable statement with a single entry at the
14383 // top and a single exit at the bottom.
14384 // The point of exit cannot be a branch out of the structured block.
14385 // longjmp() and throw() must not violate the entry/exit criteria.
14386 CS->getCapturedDecl()->setNothrow();
14387 }
14388
14389 OMPLoopBasedDirective::HelperExprs B;
14390 // In presence of clause 'collapse' with number of loops, it will
14391 // define the nested loops number.
14392 unsigned NestedLoopCount =
14393 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14394 getCollapseNumberExpr(Clauses),
14395 nullptr /*ordered not a clause on distribute*/, CS, *this,
14396 *DSAStack, VarsWithImplicitDSA, B);
14397 if (NestedLoopCount == 0)
14398 return StmtError();
14399
14400 assert((CurContext->isDependentContext() || B.builtAll()) &&
14401 "omp target teams distribute parallel for simd loop exprs were not "
14402 "built");
14403
14405 // Finalize the clauses that need pre-built expressions for CodeGen.
14406 for (OMPClause *C : Clauses) {
14407 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14408 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14409 B.NumIterations, *this, CurScope,
14410 DSAStack))
14411 return StmtError();
14412 }
14413 }
14414
14415 if (checkSimdlenSafelenSpecified(*this, Clauses))
14416 return StmtError();
14417
14420 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14421}
14422
14424 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14425 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14426 if (!AStmt)
14427 return StmtError();
14428
14429 auto *CS = cast<CapturedStmt>(AStmt);
14430 // 1.2.2 OpenMP Language Terminology
14431 // Structured block - An executable statement with a single entry at the
14432 // top and a single exit at the bottom.
14433 // The point of exit cannot be a branch out of the structured block.
14434 // longjmp() and throw() must not violate the entry/exit criteria.
14435 CS->getCapturedDecl()->setNothrow();
14436 for (int ThisCaptureLevel =
14437 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14438 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14440 // 1.2.2 OpenMP Language Terminology
14441 // Structured block - An executable statement with a single entry at the
14442 // top and a single exit at the bottom.
14443 // The point of exit cannot be a branch out of the structured block.
14444 // longjmp() and throw() must not violate the entry/exit criteria.
14445 CS->getCapturedDecl()->setNothrow();
14446 }
14447
14448 OMPLoopBasedDirective::HelperExprs B;
14449 // In presence of clause 'collapse' with number of loops, it will
14450 // define the nested loops number.
14451 unsigned NestedLoopCount = checkOpenMPLoop(
14452 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14453 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14454 VarsWithImplicitDSA, B);
14455 if (NestedLoopCount == 0)
14456 return StmtError();
14457
14458 assert((CurContext->isDependentContext() || B.builtAll()) &&
14459 "omp target teams distribute simd loop exprs were not built");
14460
14462 // Finalize the clauses that need pre-built expressions for CodeGen.
14463 for (OMPClause *C : Clauses) {
14464 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14465 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14466 B.NumIterations, *this, CurScope,
14467 DSAStack))
14468 return StmtError();
14469 }
14470 }
14471
14472 if (checkSimdlenSafelenSpecified(*this, Clauses))
14473 return StmtError();
14474
14477 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14478}
14479
14480bool Sema::checkTransformableLoopNest(
14481 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14483 Stmt *&Body,
14484 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14485 &OriginalInits) {
14486 OriginalInits.emplace_back();
14487 bool Result = OMPLoopBasedDirective::doForAllLoops(
14488 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14489 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14490 Stmt *CurStmt) {
14491 VarsWithInheritedDSAType TmpDSA;
14492 unsigned SingleNumLoops =
14493 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
14494 TmpDSA, LoopHelpers[Cnt]);
14495 if (SingleNumLoops == 0)
14496 return true;
14497 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14498 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14499 OriginalInits.back().push_back(For->getInit());
14500 Body = For->getBody();
14501 } else {
14502 assert(isa<CXXForRangeStmt>(CurStmt) &&
14503 "Expected canonical for or range-based for loops.");
14504 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14505 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14506 Body = CXXFor->getBody();
14507 }
14508 OriginalInits.emplace_back();
14509 return false;
14510 },
14511 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14512 Stmt *DependentPreInits;
14513 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14514 DependentPreInits = Dir->getPreInits();
14515 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14516 DependentPreInits = Dir->getPreInits();
14517 else
14518 llvm_unreachable("Unhandled loop transformation");
14519 if (!DependentPreInits)
14520 return;
14521 llvm::append_range(OriginalInits.back(),
14522 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14523 });
14524 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14525 OriginalInits.pop_back();
14526 return Result;
14527}
14528
14530 Stmt *AStmt, SourceLocation StartLoc,
14531 SourceLocation EndLoc) {
14532 auto SizesClauses =
14533 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14534 if (SizesClauses.empty()) {
14535 // A missing 'sizes' clause is already reported by the parser.
14536 return StmtError();
14537 }
14538 const OMPSizesClause *SizesClause = *SizesClauses.begin();
14539 unsigned NumLoops = SizesClause->getNumSizes();
14540
14541 // Empty statement should only be possible if there already was an error.
14542 if (!AStmt)
14543 return StmtError();
14544
14545 // Verify and diagnose loop nest.
14547 Stmt *Body = nullptr;
14549 OriginalInits;
14550 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14551 OriginalInits))
14552 return StmtError();
14553
14554 // Delay tiling to when template is completely instantiated.
14556 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14557 NumLoops, AStmt, nullptr, nullptr);
14558
14559 SmallVector<Decl *, 4> PreInits;
14560
14561 // Create iteration variables for the generated loops.
14562 SmallVector<VarDecl *, 4> FloorIndVars;
14563 SmallVector<VarDecl *, 4> TileIndVars;
14564 FloorIndVars.resize(NumLoops);
14565 TileIndVars.resize(NumLoops);
14566 for (unsigned I = 0; I < NumLoops; ++I) {
14567 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14568
14569 assert(LoopHelper.Counters.size() == 1 &&
14570 "Expect single-dimensional loop iteration space");
14571 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14572 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14573 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14574 QualType CntTy = IterVarRef->getType();
14575
14576 // Iteration variable for the floor (i.e. outer) loop.
14577 {
14578 std::string FloorCntName =
14579 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14580 VarDecl *FloorCntDecl =
14581 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14582 FloorIndVars[I] = FloorCntDecl;
14583 }
14584
14585 // Iteration variable for the tile (i.e. inner) loop.
14586 {
14587 std::string TileCntName =
14588 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14589
14590 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14591 // used by the expressions to derive the original iteration variable's
14592 // value from the logical iteration number.
14593 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14594 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
14595 TileIndVars[I] = TileCntDecl;
14596 }
14597 for (auto &P : OriginalInits[I]) {
14598 if (auto *D = P.dyn_cast<Decl *>())
14599 PreInits.push_back(D);
14600 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14601 PreInits.append(PI->decl_begin(), PI->decl_end());
14602 }
14603 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14604 PreInits.append(PI->decl_begin(), PI->decl_end());
14605 // Gather declarations for the data members used as counters.
14606 for (Expr *CounterRef : LoopHelper.Counters) {
14607 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14608 if (isa<OMPCapturedExprDecl>(CounterDecl))
14609 PreInits.push_back(CounterDecl);
14610 }
14611 }
14612
14613 // Once the original iteration values are set, append the innermost body.
14614 Stmt *Inner = Body;
14615
14616 // Create tile loops from the inside to the outside.
14617 for (int I = NumLoops - 1; I >= 0; --I) {
14618 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14619 Expr *NumIterations = LoopHelper.NumIterations;
14620 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14621 QualType CntTy = OrigCntVar->getType();
14622 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14623 Scope *CurScope = getCurScope();
14624
14625 // Commonly used variables.
14626 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
14627 OrigCntVar->getExprLoc());
14628 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14629 OrigCntVar->getExprLoc());
14630
14631 // For init-statement: auto .tile.iv = .floor.iv
14632 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
14633 /*DirectInit=*/false);
14634 Decl *CounterDecl = TileIndVars[I];
14635 StmtResult InitStmt = new (Context)
14636 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14637 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14638 if (!InitStmt.isUsable())
14639 return StmtError();
14640
14641 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
14642 // NumIterations)
14643 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14644 BO_Add, FloorIV, DimTileSize);
14645 if (!EndOfTile.isUsable())
14646 return StmtError();
14647 ExprResult IsPartialTile =
14648 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14649 NumIterations, EndOfTile.get());
14650 if (!IsPartialTile.isUsable())
14651 return StmtError();
14652 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
14653 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14654 IsPartialTile.get(), NumIterations, EndOfTile.get());
14655 if (!MinTileAndIterSpace.isUsable())
14656 return StmtError();
14657 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14658 BO_LT, TileIV, MinTileAndIterSpace.get());
14659 if (!CondExpr.isUsable())
14660 return StmtError();
14661
14662 // For incr-statement: ++.tile.iv
14663 ExprResult IncrStmt =
14664 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
14665 if (!IncrStmt.isUsable())
14666 return StmtError();
14667
14668 // Statements to set the original iteration variable's value from the
14669 // logical iteration number.
14670 // Generated for loop is:
14671 // Original_for_init;
14672 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
14673 // NumIterations); ++.tile.iv) {
14674 // Original_Body;
14675 // Original_counter_update;
14676 // }
14677 // FIXME: If the innermost body is an loop itself, inserting these
14678 // statements stops it being recognized as a perfectly nested loop (e.g.
14679 // for applying tiling again). If this is the case, sink the expressions
14680 // further into the inner loop.
14681 SmallVector<Stmt *, 4> BodyParts;
14682 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14683 BodyParts.push_back(Inner);
14684 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14685 Inner->getBeginLoc(), Inner->getEndLoc());
14686 Inner = new (Context)
14687 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14688 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14689 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14690 }
14691
14692 // Create floor loops from the inside to the outside.
14693 for (int I = NumLoops - 1; I >= 0; --I) {
14694 auto &LoopHelper = LoopHelpers[I];
14695 Expr *NumIterations = LoopHelper.NumIterations;
14696 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14697 QualType CntTy = OrigCntVar->getType();
14698 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14699 Scope *CurScope = getCurScope();
14700
14701 // Commonly used variables.
14702 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14703 OrigCntVar->getExprLoc());
14704
14705 // For init-statement: auto .floor.iv = 0
14707 FloorIndVars[I],
14708 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14709 /*DirectInit=*/false);
14710 Decl *CounterDecl = FloorIndVars[I];
14711 StmtResult InitStmt = new (Context)
14712 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14713 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14714 if (!InitStmt.isUsable())
14715 return StmtError();
14716
14717 // For cond-expression: .floor.iv < NumIterations
14718 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14719 BO_LT, FloorIV, NumIterations);
14720 if (!CondExpr.isUsable())
14721 return StmtError();
14722
14723 // For incr-statement: .floor.iv += DimTileSize
14724 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
14725 BO_AddAssign, FloorIV, DimTileSize);
14726 if (!IncrStmt.isUsable())
14727 return StmtError();
14728
14729 Inner = new (Context)
14730 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14731 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14732 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14733 }
14734
14735 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14736 AStmt, Inner,
14737 buildPreInits(Context, PreInits));
14738}
14739
14741 Stmt *AStmt,
14742 SourceLocation StartLoc,
14743 SourceLocation EndLoc) {
14744 // Empty statement should only be possible if there already was an error.
14745 if (!AStmt)
14746 return StmtError();
14747
14748 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
14749 return StmtError();
14750
14751 const OMPFullClause *FullClause =
14752 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14753 const OMPPartialClause *PartialClause =
14754 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14755 assert(!(FullClause && PartialClause) &&
14756 "mutual exclusivity must have been checked before");
14757
14758 constexpr unsigned NumLoops = 1;
14759 Stmt *Body = nullptr;
14761 NumLoops);
14763 OriginalInits;
14764 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14765 Body, OriginalInits))
14766 return StmtError();
14767
14768 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14769
14770 // Delay unrolling to when template is completely instantiated.
14772 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14773 NumGeneratedLoops, nullptr, nullptr);
14774
14775 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14776
14777 if (FullClause) {
14778 if (!VerifyPositiveIntegerConstantInClause(
14779 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14780 /*SuppressExprDiags=*/true)
14781 .isUsable()) {
14782 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14783 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14784 << "#pragma omp unroll full";
14785 return StmtError();
14786 }
14787 }
14788
14789 // The generated loop may only be passed to other loop-associated directive
14790 // when a partial clause is specified. Without the requirement it is
14791 // sufficient to generate loop unroll metadata at code-generation.
14792 if (NumGeneratedLoops == 0)
14793 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14794 NumGeneratedLoops, nullptr, nullptr);
14795
14796 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14797 // associated with another loop directive.
14798 //
14799 // The canonical loop analysis return by checkTransformableLoopNest assumes
14800 // the following structure to be the same loop without transformations or
14801 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14802 // LoopHelper.Counters;
14803 // for (; IV < LoopHelper.NumIterations; ++IV) {
14804 // LoopHelper.Updates;
14805 // Body;
14806 // }
14807 // \endcode
14808 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14809 // and referenced by LoopHelper.IterationVarRef.
14810 //
14811 // The unrolling directive transforms this into the following loop:
14812 // \code
14813 // OriginalInits; \
14814 // LoopHelper.PreInits; > NewPreInits
14815 // LoopHelper.Counters; /
14816 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14817 // #pragma clang loop unroll_count(Factor)
14818 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14819 // {
14820 // LoopHelper.Updates;
14821 // Body;
14822 // }
14823 // }
14824 // \endcode
14825 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14826 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14827 // references it. If the partially unrolled loop is associated with another
14828 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14829 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14830 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14831 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14832 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14833 // property of the OMPLoopBasedDirective instead of statements in
14834 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14835 // of a canonical loop nest where these PreInits are emitted before the
14836 // outermost directive.
14837
14838 // Determine the PreInit declarations.
14839 SmallVector<Decl *, 4> PreInits;
14840 assert(OriginalInits.size() == 1 &&
14841 "Expecting a single-dimensional loop iteration space");
14842 for (auto &P : OriginalInits[0]) {
14843 if (auto *D = P.dyn_cast<Decl *>())
14844 PreInits.push_back(D);
14845 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14846 PreInits.append(PI->decl_begin(), PI->decl_end());
14847 }
14848 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14849 PreInits.append(PI->decl_begin(), PI->decl_end());
14850 // Gather declarations for the data members used as counters.
14851 for (Expr *CounterRef : LoopHelper.Counters) {
14852 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14853 if (isa<OMPCapturedExprDecl>(CounterDecl))
14854 PreInits.push_back(CounterDecl);
14855 }
14856
14857 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14858 QualType IVTy = IterationVarRef->getType();
14859 assert(LoopHelper.Counters.size() == 1 &&
14860 "Expecting a single-dimensional loop iteration space");
14861 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14862
14863 // Determine the unroll factor.
14864 uint64_t Factor;
14865 SourceLocation FactorLoc;
14866 if (Expr *FactorVal = PartialClause->getFactor()) {
14867 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14868 FactorLoc = FactorVal->getExprLoc();
14869 } else {
14870 // TODO: Use a better profitability model.
14871 Factor = 2;
14872 }
14873 assert(Factor > 0 && "Expected positive unroll factor");
14874 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14876 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
14877 FactorLoc);
14878 };
14879
14880 // Iteration variable SourceLocations.
14881 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14882 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14883 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14884
14885 // Internal variable names.
14886 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14887 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14888 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14889 std::string InnerTripCountName =
14890 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14891
14892 // Create the iteration variable for the unrolled loop.
14893 VarDecl *OuterIVDecl =
14894 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
14895 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14896 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
14897 };
14898
14899 // Iteration variable for the inner loop: Reuse the iteration variable created
14900 // by checkOpenMPLoop.
14901 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14902 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
14903 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14904 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
14905 };
14906
14907 // Make a copy of the NumIterations expression for each use: By the AST
14908 // constraints, every expression object in a DeclContext must be unique.
14909 CaptureVars CopyTransformer(*this);
14910 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14911 return AssertSuccess(
14912 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14913 };
14914
14915 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14916 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
14917 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
14918 StmtResult InnerInit = new (Context)
14919 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14920 if (!InnerInit.isUsable())
14921 return StmtError();
14922
14923 // Inner For cond-expression:
14924 // \code
14925 // .unroll_inner.iv < .unrolled.iv + Factor &&
14926 // .unroll_inner.iv < NumIterations
14927 // \endcode
14928 // This conjunction of two conditions allows ScalarEvolution to derive the
14929 // maximum trip count of the inner loop.
14930 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14931 BO_Add, MakeOuterRef(), MakeFactorExpr());
14932 if (!EndOfTile.isUsable())
14933 return StmtError();
14934 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14935 BO_LT, MakeInnerRef(), EndOfTile.get());
14936 if (!InnerCond1.isUsable())
14937 return StmtError();
14938 ExprResult InnerCond2 =
14939 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
14940 MakeNumIterations());
14941 if (!InnerCond2.isUsable())
14942 return StmtError();
14943 ExprResult InnerCond =
14944 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14945 InnerCond1.get(), InnerCond2.get());
14946 if (!InnerCond.isUsable())
14947 return StmtError();
14948
14949 // Inner For incr-statement: ++.unroll_inner.iv
14950 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14951 UO_PreInc, MakeInnerRef());
14952 if (!InnerIncr.isUsable())
14953 return StmtError();
14954
14955 // Inner For statement.
14956 SmallVector<Stmt *> InnerBodyStmts;
14957 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14958 InnerBodyStmts.push_back(Body);
14959 CompoundStmt *InnerBody =
14961 Body->getBeginLoc(), Body->getEndLoc());
14962 ForStmt *InnerFor = new (Context)
14963 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14964 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14965 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14966
14967 // Unroll metadata for the inner loop.
14968 // This needs to take into account the remainder portion of the unrolled loop,
14969 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14970 // supports multiple loop exits. Instead, unroll using a factor equivalent to
14971 // the maximum trip count, which will also generate a remainder loop. Just
14972 // `unroll(enable)` (which could have been useful if the user has not
14973 // specified a concrete factor; even though the outer loop cannot be
14974 // influenced anymore, would avoid more code bloat than necessary) will refuse
14975 // the loop because "Won't unroll; remainder loop could not be generated when
14976 // assuming runtime trip count". Even if it did work, it must not choose a
14977 // larger unroll factor than the maximum loop length, or it would always just
14978 // execute the remainder loop.
14979 LoopHintAttr *UnrollHintAttr =
14980 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14981 LoopHintAttr::Numeric, MakeFactorExpr());
14982 AttributedStmt *InnerUnrolled =
14983 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
14984
14985 // Outer For init-statement: auto .unrolled.iv = 0
14987 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14988 /*DirectInit=*/false);
14989 StmtResult OuterInit = new (Context)
14990 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14991 if (!OuterInit.isUsable())
14992 return StmtError();
14993
14994 // Outer For cond-expression: .unrolled.iv < NumIterations
14995 ExprResult OuterConde =
14996 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
14997 MakeNumIterations());
14998 if (!OuterConde.isUsable())
14999 return StmtError();
15000
15001 // Outer For incr-statement: .unrolled.iv += Factor
15002 ExprResult OuterIncr =
15003 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15004 MakeOuterRef(), MakeFactorExpr());
15005 if (!OuterIncr.isUsable())
15006 return StmtError();
15007
15008 // Outer For statement.
15009 ForStmt *OuterFor = new (Context)
15010 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15011 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15012 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15013
15014 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15015 NumGeneratedLoops, OuterFor,
15016 buildPreInits(Context, PreInits));
15017}
15018
15020 SourceLocation StartLoc,
15021 SourceLocation LParenLoc,
15022 SourceLocation EndLoc) {
15023 OMPClause *Res = nullptr;
15024 switch (Kind) {
15025 case OMPC_final:
15026 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15027 break;
15028 case OMPC_num_threads:
15029 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15030 break;
15031 case OMPC_safelen:
15032 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15033 break;
15034 case OMPC_simdlen:
15035 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15036 break;
15037 case OMPC_allocator:
15038 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15039 break;
15040 case OMPC_collapse:
15041 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15042 break;
15043 case OMPC_ordered:
15044 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15045 break;
15046 case OMPC_num_teams:
15047 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15048 break;
15049 case OMPC_thread_limit:
15050 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15051 break;
15052 case OMPC_priority:
15053 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15054 break;
15055 case OMPC_grainsize:
15056 Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc);
15057 break;
15058 case OMPC_num_tasks:
15059 Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc);
15060 break;
15061 case OMPC_hint:
15062 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15063 break;
15064 case OMPC_depobj:
15065 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15066 break;
15067 case OMPC_detach:
15068 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15069 break;
15070 case OMPC_novariants:
15071 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15072 break;
15073 case OMPC_nocontext:
15074 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15075 break;
15076 case OMPC_filter:
15077 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15078 break;
15079 case OMPC_partial:
15080 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15081 break;
15082 case OMPC_align:
15083 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15084 break;
15085 case OMPC_device:
15086 case OMPC_if:
15087 case OMPC_default:
15088 case OMPC_proc_bind:
15089 case OMPC_schedule:
15090 case OMPC_private:
15091 case OMPC_firstprivate:
15092 case OMPC_lastprivate:
15093 case OMPC_shared:
15094 case OMPC_reduction:
15095 case OMPC_task_reduction:
15096 case OMPC_in_reduction:
15097 case OMPC_linear:
15098 case OMPC_aligned:
15099 case OMPC_copyin:
15100 case OMPC_copyprivate:
15101 case OMPC_nowait:
15102 case OMPC_untied:
15103 case OMPC_mergeable:
15104 case OMPC_threadprivate:
15105 case OMPC_sizes:
15106 case OMPC_allocate:
15107 case OMPC_flush:
15108 case OMPC_read:
15109 case OMPC_write:
15110 case OMPC_update:
15111 case OMPC_capture:
15112 case OMPC_compare:
15113 case OMPC_seq_cst:
15114 case OMPC_acq_rel:
15115 case OMPC_acquire:
15116 case OMPC_release:
15117 case OMPC_relaxed:
15118 case OMPC_depend:
15119 case OMPC_threads:
15120 case OMPC_simd:
15121 case OMPC_map:
15122 case OMPC_nogroup:
15123 case OMPC_dist_schedule:
15124 case OMPC_defaultmap:
15125 case OMPC_unknown:
15126 case OMPC_uniform:
15127 case OMPC_to:
15128 case OMPC_from:
15129 case OMPC_use_device_ptr:
15130 case OMPC_use_device_addr:
15131 case OMPC_is_device_ptr:
15132 case OMPC_unified_address:
15133 case OMPC_unified_shared_memory:
15134 case OMPC_reverse_offload:
15135 case OMPC_dynamic_allocators:
15136 case OMPC_atomic_default_mem_order:
15137 case OMPC_device_type:
15138 case OMPC_match:
15139 case OMPC_nontemporal:
15140 case OMPC_order:
15141 case OMPC_destroy:
15142 case OMPC_inclusive:
15143 case OMPC_exclusive:
15144 case OMPC_uses_allocators:
15145 case OMPC_affinity:
15146 case OMPC_when:
15147 case OMPC_bind:
15148 default:
15149 llvm_unreachable("Clause is not allowed.");
15150 }
15151 return Res;
15152}
15153
15154// An OpenMP directive such as 'target parallel' has two captured regions:
15155// for the 'target' and 'parallel' respectively. This function returns
15156// the region in which to capture expressions associated with a clause.
15157// A return value of OMPD_unknown signifies that the expression should not
15158// be captured.
15160 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15161 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15162 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15163 switch (CKind) {
15164 case OMPC_if:
15165 switch (DKind) {
15166 case OMPD_target_parallel_for_simd:
15167 if (OpenMPVersion >= 50 &&
15168 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15169 CaptureRegion = OMPD_parallel;
15170 break;
15171 }
15172 LLVM_FALLTHROUGH;
15173 case OMPD_target_parallel:
15174 case OMPD_target_parallel_for:
15175 case OMPD_target_parallel_loop:
15176 // If this clause applies to the nested 'parallel' region, capture within
15177 // the 'target' region, otherwise do not capture.
15178 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15179 CaptureRegion = OMPD_target;
15180 break;
15181 case OMPD_target_teams_distribute_parallel_for_simd:
15182 if (OpenMPVersion >= 50 &&
15183 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15184 CaptureRegion = OMPD_parallel;
15185 break;
15186 }
15187 LLVM_FALLTHROUGH;
15188 case OMPD_target_teams_distribute_parallel_for:
15189 // If this clause applies to the nested 'parallel' region, capture within
15190 // the 'teams' region, otherwise do not capture.
15191 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15192 CaptureRegion = OMPD_teams;
15193 break;
15194 case OMPD_teams_distribute_parallel_for_simd:
15195 if (OpenMPVersion >= 50 &&
15196 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15197 CaptureRegion = OMPD_parallel;
15198 break;
15199 }
15200 LLVM_FALLTHROUGH;
15201 case OMPD_teams_distribute_parallel_for:
15202 CaptureRegion = OMPD_teams;
15203 break;
15204 case OMPD_target_update:
15205 case OMPD_target_enter_data:
15206 case OMPD_target_exit_data:
15207 CaptureRegion = OMPD_task;
15208 break;
15209 case OMPD_parallel_masked_taskloop:
15210 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15211 CaptureRegion = OMPD_parallel;
15212 break;
15213 case OMPD_parallel_master_taskloop:
15214 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15215 CaptureRegion = OMPD_parallel;
15216 break;
15217 case OMPD_parallel_masked_taskloop_simd:
15218 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15219 NameModifier == OMPD_taskloop) {
15220 CaptureRegion = OMPD_parallel;
15221 break;
15222 }
15223 if (OpenMPVersion <= 45)
15224 break;
15225 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15226 CaptureRegion = OMPD_taskloop;
15227 break;
15228 case OMPD_parallel_master_taskloop_simd:
15229 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15230 NameModifier == OMPD_taskloop) {
15231 CaptureRegion = OMPD_parallel;
15232 break;
15233 }
15234 if (OpenMPVersion <= 45)
15235 break;
15236 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15237 CaptureRegion = OMPD_taskloop;
15238 break;
15239 case OMPD_parallel_for_simd:
15240 if (OpenMPVersion <= 45)
15241 break;
15242 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15243 CaptureRegion = OMPD_parallel;
15244 break;
15245 case OMPD_taskloop_simd:
15246 case OMPD_master_taskloop_simd:
15247 case OMPD_masked_taskloop_simd:
15248 if (OpenMPVersion <= 45)
15249 break;
15250 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15251 CaptureRegion = OMPD_taskloop;
15252 break;
15253 case OMPD_distribute_parallel_for_simd:
15254 if (OpenMPVersion <= 45)
15255 break;
15256 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15257 CaptureRegion = OMPD_parallel;
15258 break;
15259 case OMPD_target_simd:
15260 if (OpenMPVersion >= 50 &&
15261 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15262 CaptureRegion = OMPD_target;
15263 break;
15264 case OMPD_teams_distribute_simd:
15265 case OMPD_target_teams_distribute_simd:
15266 if (OpenMPVersion >= 50 &&
15267 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15268 CaptureRegion = OMPD_teams;
15269 break;
15270 case OMPD_cancel:
15271 case OMPD_parallel:
15272 case OMPD_parallel_master:
15273 case OMPD_parallel_masked:
15274 case OMPD_parallel_sections:
15275 case OMPD_parallel_for:
15276 case OMPD_parallel_loop:
15277 case OMPD_target:
15278 case OMPD_target_teams:
15279 case OMPD_target_teams_distribute:
15280 case OMPD_target_teams_loop:
15281 case OMPD_distribute_parallel_for:
15282 case OMPD_task:
15283 case OMPD_taskloop:
15284 case OMPD_master_taskloop:
15285 case OMPD_masked_taskloop:
15286 case OMPD_target_data:
15287 case OMPD_simd:
15288 case OMPD_for_simd:
15289 case OMPD_distribute_simd:
15290 // Do not capture if-clause expressions.
15291 break;
15292 case OMPD_threadprivate:
15293 case OMPD_allocate:
15294 case OMPD_taskyield:
15295 case OMPD_barrier:
15296 case OMPD_taskwait:
15297 case OMPD_cancellation_point:
15298 case OMPD_flush:
15299 case OMPD_depobj:
15300 case OMPD_scan:
15301 case OMPD_declare_reduction:
15302 case OMPD_declare_mapper:
15303 case OMPD_declare_simd:
15304 case OMPD_declare_variant:
15305 case OMPD_begin_declare_variant:
15306 case OMPD_end_declare_variant:
15307 case OMPD_declare_target:
15308 case OMPD_end_declare_target:
15309 case OMPD_loop:
15310 case OMPD_teams_loop:
15311 case OMPD_teams:
15312 case OMPD_tile:
15313 case OMPD_unroll:
15314 case OMPD_for:
15315 case OMPD_sections:
15316 case OMPD_section:
15317 case OMPD_single:
15318 case OMPD_master:
15319 case OMPD_masked:
15320 case OMPD_critical:
15321 case OMPD_taskgroup:
15322 case OMPD_distribute:
15323 case OMPD_ordered:
15324 case OMPD_atomic:
15325 case OMPD_teams_distribute:
15326 case OMPD_requires:
15327 case OMPD_metadirective:
15328 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15329 case OMPD_unknown:
15330 default:
15331 llvm_unreachable("Unknown OpenMP directive");
15332 }
15333 break;
15334 case OMPC_num_threads:
15335 switch (DKind) {
15336 case OMPD_target_parallel:
15337 case OMPD_target_parallel_for:
15338 case OMPD_target_parallel_for_simd:
15339 case OMPD_target_parallel_loop:
15340 CaptureRegion = OMPD_target;
15341 break;
15342 case OMPD_teams_distribute_parallel_for:
15343 case OMPD_teams_distribute_parallel_for_simd:
15344 case OMPD_target_teams_distribute_parallel_for:
15345 case OMPD_target_teams_distribute_parallel_for_simd:
15346 CaptureRegion = OMPD_teams;
15347 break;
15348 case OMPD_parallel:
15349 case OMPD_parallel_master:
15350 case OMPD_parallel_masked:
15351 case OMPD_parallel_sections:
15352 case OMPD_parallel_for:
15353 case OMPD_parallel_for_simd:
15354 case OMPD_parallel_loop:
15355 case OMPD_distribute_parallel_for:
15356 case OMPD_distribute_parallel_for_simd:
15357 case OMPD_parallel_master_taskloop:
15358 case OMPD_parallel_masked_taskloop:
15359 case OMPD_parallel_master_taskloop_simd:
15360 case OMPD_parallel_masked_taskloop_simd:
15361 // Do not capture num_threads-clause expressions.
15362 break;
15363 case OMPD_target_data:
15364 case OMPD_target_enter_data:
15365 case OMPD_target_exit_data:
15366 case OMPD_target_update:
15367 case OMPD_target:
15368 case OMPD_target_simd:
15369 case OMPD_target_teams:
15370 case OMPD_target_teams_distribute:
15371 case OMPD_target_teams_distribute_simd:
15372 case OMPD_cancel:
15373 case OMPD_task:
15374 case OMPD_taskloop:
15375 case OMPD_taskloop_simd:
15376 case OMPD_master_taskloop:
15377 case OMPD_masked_taskloop:
15378 case OMPD_master_taskloop_simd:
15379 case OMPD_masked_taskloop_simd:
15380 case OMPD_threadprivate:
15381 case OMPD_allocate:
15382 case OMPD_taskyield:
15383 case OMPD_barrier:
15384 case OMPD_taskwait:
15385 case OMPD_cancellation_point:
15386 case OMPD_flush:
15387 case OMPD_depobj:
15388 case OMPD_scan:
15389 case OMPD_declare_reduction:
15390 case OMPD_declare_mapper:
15391 case OMPD_declare_simd:
15392 case OMPD_declare_variant:
15393 case OMPD_begin_declare_variant:
15394 case OMPD_end_declare_variant:
15395 case OMPD_declare_target:
15396 case OMPD_end_declare_target:
15397 case OMPD_loop:
15398 case OMPD_teams_loop:
15399 case OMPD_target_teams_loop:
15400 case OMPD_teams:
15401 case OMPD_simd:
15402 case OMPD_tile:
15403 case OMPD_unroll:
15404 case OMPD_for:
15405 case OMPD_for_simd:
15406 case OMPD_sections:
15407 case OMPD_section:
15408 case OMPD_single:
15409 case OMPD_master:
15410 case OMPD_masked:
15411 case OMPD_critical:
15412 case OMPD_taskgroup:
15413 case OMPD_distribute:
15414 case OMPD_ordered:
15415 case OMPD_atomic:
15416 case OMPD_distribute_simd:
15417 case OMPD_teams_distribute:
15418 case OMPD_teams_distribute_simd:
15419 case OMPD_requires:
15420 case OMPD_metadirective:
15421 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15422 case OMPD_unknown:
15423 default:
15424 llvm_unreachable("Unknown OpenMP directive");
15425 }
15426 break;
15427 case OMPC_num_teams:
15428 switch (DKind) {
15429 case OMPD_target_teams:
15430 case OMPD_target_teams_distribute:
15431 case OMPD_target_teams_distribute_simd:
15432 case OMPD_target_teams_distribute_parallel_for:
15433 case OMPD_target_teams_distribute_parallel_for_simd:
15434 case OMPD_target_teams_loop:
15435 CaptureRegion = OMPD_target;
15436 break;
15437 case OMPD_teams_distribute_parallel_for:
15438 case OMPD_teams_distribute_parallel_for_simd:
15439 case OMPD_teams:
15440 case OMPD_teams_distribute:
15441 case OMPD_teams_distribute_simd:
15442 case OMPD_teams_loop:
15443 // Do not capture num_teams-clause expressions.
15444 break;
15445 case OMPD_distribute_parallel_for:
15446 case OMPD_distribute_parallel_for_simd:
15447 case OMPD_task:
15448 case OMPD_taskloop:
15449 case OMPD_taskloop_simd:
15450 case OMPD_master_taskloop:
15451 case OMPD_masked_taskloop:
15452 case OMPD_master_taskloop_simd:
15453 case OMPD_masked_taskloop_simd:
15454 case OMPD_parallel_master_taskloop:
15455 case OMPD_parallel_masked_taskloop:
15456 case OMPD_parallel_master_taskloop_simd:
15457 case OMPD_parallel_masked_taskloop_simd:
15458 case OMPD_target_data:
15459 case OMPD_target_enter_data:
15460 case OMPD_target_exit_data:
15461 case OMPD_target_update:
15462 case OMPD_cancel:
15463 case OMPD_parallel:
15464 case OMPD_parallel_master:
15465 case OMPD_parallel_masked:
15466 case OMPD_parallel_sections:
15467 case OMPD_parallel_for:
15468 case OMPD_parallel_for_simd:
15469 case OMPD_parallel_loop:
15470 case OMPD_target:
15471 case OMPD_target_simd:
15472 case OMPD_target_parallel:
15473 case OMPD_target_parallel_for:
15474 case OMPD_target_parallel_for_simd:
15475 case OMPD_target_parallel_loop:
15476 case OMPD_threadprivate:
15477 case OMPD_allocate:
15478 case OMPD_taskyield:
15479 case OMPD_barrier:
15480 case OMPD_taskwait:
15481 case OMPD_cancellation_point:
15482 case OMPD_flush:
15483 case OMPD_depobj:
15484 case OMPD_scan:
15485 case OMPD_declare_reduction:
15486 case OMPD_declare_mapper:
15487 case OMPD_declare_simd:
15488 case OMPD_declare_variant:
15489 case OMPD_begin_declare_variant:
15490 case OMPD_end_declare_variant:
15491 case OMPD_declare_target:
15492 case OMPD_end_declare_target:
15493 case OMPD_loop:
15494 case OMPD_simd:
15495 case OMPD_tile:
15496 case OMPD_unroll:
15497 case OMPD_for:
15498 case OMPD_for_simd:
15499 case OMPD_sections:
15500 case OMPD_section:
15501 case OMPD_single:
15502 case OMPD_master:
15503 case OMPD_masked:
15504 case OMPD_critical:
15505 case OMPD_taskgroup:
15506 case OMPD_distribute:
15507 case OMPD_ordered:
15508 case OMPD_atomic:
15509 case OMPD_distribute_simd:
15510 case OMPD_requires:
15511 case OMPD_metadirective:
15512 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15513 case OMPD_unknown:
15514 default:
15515 llvm_unreachable("Unknown OpenMP directive");
15516 }
15517 break;
15518 case OMPC_thread_limit:
15519 switch (DKind) {
15520 case OMPD_target_teams:
15521 case OMPD_target_teams_distribute:
15522 case OMPD_target_teams_distribute_simd:
15523 case OMPD_target_teams_distribute_parallel_for:
15524 case OMPD_target_teams_distribute_parallel_for_simd:
15525 case OMPD_target_teams_loop:
15526 CaptureRegion = OMPD_target;
15527 break;
15528 case OMPD_teams_distribute_parallel_for:
15529 case OMPD_teams_distribute_parallel_for_simd:
15530 case OMPD_teams:
15531 case OMPD_teams_distribute:
15532 case OMPD_teams_distribute_simd:
15533 case OMPD_teams_loop:
15534 // Do not capture thread_limit-clause expressions.
15535 break;
15536 case OMPD_distribute_parallel_for:
15537 case OMPD_distribute_parallel_for_simd:
15538 case OMPD_task:
15539 case OMPD_taskloop:
15540 case OMPD_taskloop_simd:
15541 case OMPD_master_taskloop:
15542 case OMPD_masked_taskloop:
15543 case OMPD_master_taskloop_simd:
15544 case OMPD_masked_taskloop_simd:
15545 case OMPD_parallel_master_taskloop:
15546 case OMPD_parallel_masked_taskloop:
15547 case OMPD_parallel_master_taskloop_simd:
15548 case OMPD_parallel_masked_taskloop_simd:
15549 case OMPD_target_data:
15550 case OMPD_target_enter_data:
15551 case OMPD_target_exit_data:
15552 case OMPD_target_update:
15553 case OMPD_cancel:
15554 case OMPD_parallel:
15555 case OMPD_parallel_master:
15556 case OMPD_parallel_masked:
15557 case OMPD_parallel_sections:
15558 case OMPD_parallel_for:
15559 case OMPD_parallel_for_simd:
15560 case OMPD_parallel_loop:
15561 case OMPD_target:
15562 case OMPD_target_simd:
15563 case OMPD_target_parallel:
15564 case OMPD_target_parallel_for:
15565 case OMPD_target_parallel_for_simd:
15566 case OMPD_target_parallel_loop:
15567 case OMPD_threadprivate:
15568 case OMPD_allocate:
15569 case OMPD_taskyield:
15570 case OMPD_barrier:
15571 case OMPD_taskwait:
15572 case OMPD_cancellation_point:
15573 case OMPD_flush:
15574 case OMPD_depobj:
15575 case OMPD_scan:
15576 case OMPD_declare_reduction:
15577 case OMPD_declare_mapper:
15578 case OMPD_declare_simd:
15579 case OMPD_declare_variant:
15580 case OMPD_begin_declare_variant:
15581 case OMPD_end_declare_variant:
15582 case OMPD_declare_target:
15583 case OMPD_end_declare_target:
15584 case OMPD_loop:
15585 case OMPD_simd:
15586 case OMPD_tile:
15587 case OMPD_unroll:
15588 case OMPD_for:
15589 case OMPD_for_simd:
15590 case OMPD_sections:
15591 case OMPD_section:
15592 case OMPD_single:
15593 case OMPD_master:
15594 case OMPD_masked:
15595 case OMPD_critical:
15596 case OMPD_taskgroup:
15597 case OMPD_distribute:
15598 case OMPD_ordered:
15599 case OMPD_atomic:
15600 case OMPD_distribute_simd:
15601 case OMPD_requires:
15602 case OMPD_metadirective:
15603 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
15604 case OMPD_unknown:
15605 default:
15606 llvm_unreachable("Unknown OpenMP directive");
15607 }
15608 break;
15609 case OMPC_schedule:
15610 switch (DKind) {
15611 case OMPD_parallel_for:
15612 case OMPD_parallel_for_simd:
15613 case OMPD_distribute_parallel_for:
15614 case OMPD_distribute_parallel_for_simd:
15615 case OMPD_teams_distribute_parallel_for:
15616 case OMPD_teams_distribute_parallel_for_simd:
15617 case OMPD_target_parallel_for:
15618 case OMPD_target_parallel_for_simd:
15619 case OMPD_target_teams_distribute_parallel_for:
15620 case OMPD_target_teams_distribute_parallel_for_simd:
15621 CaptureRegion = OMPD_parallel;
15622 break;
15623 case OMPD_for:
15624 case OMPD_for_simd:
15625 // Do not capture schedule-clause expressions.
15626 break;
15627 case OMPD_task:
15628 case OMPD_taskloop:
15629 case OMPD_taskloop_simd:
15630 case OMPD_master_taskloop:
15631 case OMPD_masked_taskloop:
15632 case OMPD_master_taskloop_simd:
15633 case OMPD_masked_taskloop_simd:
15634 case OMPD_parallel_master_taskloop:
15635 case OMPD_parallel_masked_taskloop:
15636 case OMPD_parallel_master_taskloop_simd:
15637 case OMPD_parallel_masked_taskloop_simd:
15638 case OMPD_target_data:
15639 case OMPD_target_enter_data:
15640 case OMPD_target_exit_data:
15641 case OMPD_target_update:
15642 case OMPD_teams:
15643 case OMPD_teams_distribute:
15644 case OMPD_teams_distribute_simd:
15645 case OMPD_target_teams_distribute:
15646 case OMPD_target_teams_distribute_simd:
15647 case OMPD_target:
15648 case OMPD_target_simd:
15649 case OMPD_target_parallel:
15650 case OMPD_cancel:
15651 case OMPD_parallel:
15652 case OMPD_parallel_master:
15653 case OMPD_parallel_masked:
15654 case OMPD_parallel_sections:
15655 case OMPD_threadprivate:
15656 case OMPD_allocate:
15657 case OMPD_taskyield:
15658 case OMPD_barrier:
15659 case OMPD_taskwait:
15660 case OMPD_cancellation_point:
15661 case OMPD_flush:
15662 case OMPD_depobj:
15663 case OMPD_scan:
15664 case OMPD_declare_reduction:
15665 case OMPD_declare_mapper:
15666 case OMPD_declare_simd:
15667 case OMPD_declare_variant:
15668 case OMPD_begin_declare_variant:
15669 case OMPD_end_declare_variant:
15670 case OMPD_declare_target:
15671 case OMPD_end_declare_target:
15672 case OMPD_loop:
15673 case OMPD_teams_loop:
15674 case OMPD_target_teams_loop:
15675 case OMPD_parallel_loop:
15676 case OMPD_target_parallel_loop:
15677 case OMPD_simd:
15678 case OMPD_tile:
15679 case OMPD_unroll:
15680 case OMPD_sections:
15681 case OMPD_section:
15682 case OMPD_single:
15683 case OMPD_master:
15684 case OMPD_masked:
15685 case OMPD_critical:
15686 case OMPD_taskgroup:
15687 case OMPD_distribute:
15688 case OMPD_ordered:
15689 case OMPD_atomic:
15690 case OMPD_distribute_simd:
15691 case OMPD_target_teams:
15692 case OMPD_requires:
15693 case OMPD_metadirective:
15694 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
15695 case OMPD_unknown:
15696 default:
15697 llvm_unreachable("Unknown OpenMP directive");
15698 }
15699 break;
15700 case OMPC_dist_schedule:
15701 switch (DKind) {
15702 case OMPD_teams_distribute_parallel_for:
15703 case OMPD_teams_distribute_parallel_for_simd:
15704 case OMPD_teams_distribute:
15705 case OMPD_teams_distribute_simd:
15706 case OMPD_target_teams_distribute_parallel_for:
15707 case OMPD_target_teams_distribute_parallel_for_simd:
15708 case OMPD_target_teams_distribute:
15709 case OMPD_target_teams_distribute_simd:
15710 CaptureRegion = OMPD_teams;
15711 break;
15712 case OMPD_distribute_parallel_for:
15713 case OMPD_distribute_parallel_for_simd:
15714 case OMPD_distribute:
15715 case OMPD_distribute_simd:
15716 // Do not capture dist_schedule-clause expressions.
15717 break;
15718 case OMPD_parallel_for:
15719 case OMPD_parallel_for_simd:
15720 case OMPD_target_parallel_for_simd:
15721 case OMPD_target_parallel_for:
15722 case OMPD_task:
15723 case OMPD_taskloop:
15724 case OMPD_taskloop_simd:
15725 case OMPD_master_taskloop:
15726 case OMPD_masked_taskloop:
15727 case OMPD_master_taskloop_simd:
15728 case OMPD_masked_taskloop_simd:
15729 case OMPD_parallel_master_taskloop:
15730 case OMPD_parallel_masked_taskloop:
15731 case OMPD_parallel_master_taskloop_simd:
15732 case OMPD_parallel_masked_taskloop_simd:
15733 case OMPD_target_data:
15734 case OMPD_target_enter_data:
15735 case OMPD_target_exit_data:
15736 case OMPD_target_update:
15737 case OMPD_teams:
15738 case OMPD_target:
15739 case OMPD_target_simd:
15740 case OMPD_target_parallel:
15741 case OMPD_cancel:
15742 case OMPD_parallel:
15743 case OMPD_parallel_master:
15744 case OMPD_parallel_masked:
15745 case OMPD_parallel_sections:
15746 case OMPD_threadprivate:
15747 case OMPD_allocate:
15748 case OMPD_taskyield:
15749 case OMPD_barrier:
15750 case OMPD_taskwait:
15751 case OMPD_cancellation_point:
15752 case OMPD_flush:
15753 case OMPD_depobj:
15754 case OMPD_scan:
15755 case OMPD_declare_reduction:
15756 case OMPD_declare_mapper:
15757 case OMPD_declare_simd:
15758 case OMPD_declare_variant:
15759 case OMPD_begin_declare_variant:
15760 case OMPD_end_declare_variant:
15761 case OMPD_declare_target:
15762 case OMPD_end_declare_target:
15763 case OMPD_loop:
15764 case OMPD_teams_loop:
15765 case OMPD_target_teams_loop:
15766 case OMPD_parallel_loop:
15767 case OMPD_target_parallel_loop:
15768 case OMPD_simd:
15769 case OMPD_tile:
15770 case OMPD_unroll:
15771 case OMPD_for:
15772 case OMPD_for_simd:
15773 case OMPD_sections:
15774 case OMPD_section:
15775 case OMPD_single:
15776 case OMPD_master:
15777 case OMPD_masked:
15778 case OMPD_critical:
15779 case OMPD_taskgroup:
15780 case OMPD_ordered:
15781 case OMPD_atomic:
15782 case OMPD_target_teams:
15783 case OMPD_requires:
15784 case OMPD_metadirective:
15785 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
15786 case OMPD_unknown:
15787 default:
15788 llvm_unreachable("Unknown OpenMP directive");
15789 }
15790 break;
15791 case OMPC_device:
15792 switch (DKind) {
15793 case OMPD_target_update:
15794 case OMPD_target_enter_data:
15795 case OMPD_target_exit_data:
15796 case OMPD_target:
15797 case OMPD_target_simd:
15798 case OMPD_target_teams:
15799 case OMPD_target_parallel:
15800 case OMPD_target_teams_distribute:
15801 case OMPD_target_teams_distribute_simd:
15802 case OMPD_target_parallel_for:
15803 case OMPD_target_parallel_for_simd:
15804 case OMPD_target_parallel_loop:
15805 case OMPD_target_teams_distribute_parallel_for:
15806 case OMPD_target_teams_distribute_parallel_for_simd:
15807 case OMPD_target_teams_loop:
15808 case OMPD_dispatch:
15809 CaptureRegion = OMPD_task;
15810 break;
15811 case OMPD_target_data:
15812 case OMPD_interop:
15813 // Do not capture device-clause expressions.
15814 break;
15815 case OMPD_teams_distribute_parallel_for:
15816 case OMPD_teams_distribute_parallel_for_simd:
15817 case OMPD_teams:
15818 case OMPD_teams_distribute:
15819 case OMPD_teams_distribute_simd:
15820 case OMPD_distribute_parallel_for:
15821 case OMPD_distribute_parallel_for_simd:
15822 case OMPD_task:
15823 case OMPD_taskloop:
15824 case OMPD_taskloop_simd:
15825 case OMPD_master_taskloop:
15826 case OMPD_masked_taskloop:
15827 case OMPD_master_taskloop_simd:
15828 case OMPD_masked_taskloop_simd:
15829 case OMPD_parallel_master_taskloop:
15830 case OMPD_parallel_masked_taskloop:
15831 case OMPD_parallel_master_taskloop_simd:
15832 case OMPD_parallel_masked_taskloop_simd:
15833 case OMPD_cancel:
15834 case OMPD_parallel:
15835 case OMPD_parallel_master:
15836 case OMPD_parallel_masked:
15837 case OMPD_parallel_sections:
15838 case OMPD_parallel_for:
15839 case OMPD_parallel_for_simd:
15840 case OMPD_threadprivate:
15841 case OMPD_allocate:
15842 case OMPD_taskyield:
15843 case OMPD_barrier:
15844 case OMPD_taskwait:
15845 case OMPD_cancellation_point:
15846 case OMPD_flush:
15847 case OMPD_depobj:
15848 case OMPD_scan:
15849 case OMPD_declare_reduction:
15850 case OMPD_declare_mapper:
15851 case OMPD_declare_simd:
15852 case OMPD_declare_variant:
15853 case OMPD_begin_declare_variant:
15854 case OMPD_end_declare_variant:
15855 case OMPD_declare_target:
15856 case OMPD_end_declare_target:
15857 case OMPD_loop:
15858 case OMPD_teams_loop:
15859 case OMPD_parallel_loop:
15860 case OMPD_simd:
15861 case OMPD_tile:
15862 case OMPD_unroll:
15863 case OMPD_for:
15864 case OMPD_for_simd:
15865 case OMPD_sections:
15866 case OMPD_section:
15867 case OMPD_single:
15868 case OMPD_master:
15869 case OMPD_masked:
15870 case OMPD_critical:
15871 case OMPD_taskgroup:
15872 case OMPD_distribute:
15873 case OMPD_ordered:
15874 case OMPD_atomic:
15875 case OMPD_distribute_simd:
15876 case OMPD_requires:
15877 case OMPD_metadirective:
15878 llvm_unreachable("Unexpected OpenMP directive with device-clause");
15879 case OMPD_unknown:
15880 default:
15881 llvm_unreachable("Unknown OpenMP directive");
15882 }
15883 break;
15884 case OMPC_grainsize:
15885 case OMPC_num_tasks:
15886 case OMPC_final:
15887 case OMPC_priority:
15888 switch (DKind) {
15889 case OMPD_task:
15890 case OMPD_taskloop:
15891 case OMPD_taskloop_simd:
15892 case OMPD_master_taskloop:
15893 case OMPD_masked_taskloop:
15894 case OMPD_master_taskloop_simd:
15895 case OMPD_masked_taskloop_simd:
15896 break;
15897 case OMPD_parallel_masked_taskloop:
15898 case OMPD_parallel_masked_taskloop_simd:
15899 case OMPD_parallel_master_taskloop:
15900 case OMPD_parallel_master_taskloop_simd:
15901 CaptureRegion = OMPD_parallel;
15902 break;
15903 case OMPD_target_update:
15904 case OMPD_target_enter_data:
15905 case OMPD_target_exit_data:
15906 case OMPD_target:
15907 case OMPD_target_simd:
15908 case OMPD_target_teams:
15909 case OMPD_target_parallel:
15910 case OMPD_target_teams_distribute:
15911 case OMPD_target_teams_distribute_simd:
15912 case OMPD_target_parallel_for:
15913 case OMPD_target_parallel_for_simd:
15914 case OMPD_target_teams_distribute_parallel_for:
15915 case OMPD_target_teams_distribute_parallel_for_simd:
15916 case OMPD_target_data:
15917 case OMPD_teams_distribute_parallel_for:
15918 case OMPD_teams_distribute_parallel_for_simd:
15919 case OMPD_teams:
15920 case OMPD_teams_distribute:
15921 case OMPD_teams_distribute_simd:
15922 case OMPD_distribute_parallel_for:
15923 case OMPD_distribute_parallel_for_simd:
15924 case OMPD_cancel:
15925 case OMPD_parallel:
15926 case OMPD_parallel_master:
15927 case OMPD_parallel_masked:
15928 case OMPD_parallel_sections:
15929 case OMPD_parallel_for:
15930 case OMPD_parallel_for_simd:
15931 case OMPD_threadprivate:
15932 case OMPD_allocate:
15933 case OMPD_taskyield:
15934 case OMPD_barrier:
15935 case OMPD_taskwait:
15936 case OMPD_cancellation_point:
15937 case OMPD_flush:
15938 case OMPD_depobj:
15939 case OMPD_scan:
15940 case OMPD_declare_reduction:
15941 case OMPD_declare_mapper:
15942 case OMPD_declare_simd:
15943 case OMPD_declare_variant:
15944 case OMPD_begin_declare_variant:
15945 case OMPD_end_declare_variant:
15946 case OMPD_declare_target:
15947 case OMPD_end_declare_target:
15948 case OMPD_loop:
15949 case OMPD_teams_loop:
15950 case OMPD_target_teams_loop:
15951 case OMPD_parallel_loop:
15952 case OMPD_target_parallel_loop:
15953 case OMPD_simd:
15954 case OMPD_tile:
15955 case OMPD_unroll:
15956 case OMPD_for:
15957 case OMPD_for_simd:
15958 case OMPD_sections:
15959 case OMPD_section:
15960 case OMPD_single:
15961 case OMPD_master:
15962 case OMPD_masked:
15963 case OMPD_critical:
15964 case OMPD_taskgroup:
15965 case OMPD_distribute:
15966 case OMPD_ordered:
15967 case OMPD_atomic:
15968 case OMPD_distribute_simd:
15969 case OMPD_requires:
15970 case OMPD_metadirective:
15971 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
15972 case OMPD_unknown:
15973 default:
15974 llvm_unreachable("Unknown OpenMP directive");
15975 }
15976 break;
15977 case OMPC_novariants:
15978 case OMPC_nocontext:
15979 switch (DKind) {
15980 case OMPD_dispatch:
15981 CaptureRegion = OMPD_task;
15982 break;
15983 default:
15984 llvm_unreachable("Unexpected OpenMP directive");
15985 }
15986 break;
15987 case OMPC_filter:
15988 // Do not capture filter-clause expressions.
15989 break;
15990 case OMPC_when:
15991 if (DKind == OMPD_metadirective) {
15992 CaptureRegion = OMPD_metadirective;
15993 } else if (DKind == OMPD_unknown) {
15994 llvm_unreachable("Unknown OpenMP directive");
15995 } else {
15996 llvm_unreachable("Unexpected OpenMP directive with when clause");
15997 }
15998 break;
15999 case OMPC_firstprivate:
16000 case OMPC_lastprivate:
16001 case OMPC_reduction:
16002 case OMPC_task_reduction:
16003 case OMPC_in_reduction:
16004 case OMPC_linear:
16005 case OMPC_default:
16006 case OMPC_proc_bind:
16007 case OMPC_safelen:
16008 case OMPC_simdlen:
16009 case OMPC_sizes:
16010 case OMPC_allocator:
16011 case OMPC_collapse:
16012 case OMPC_private:
16013 case OMPC_shared:
16014 case OMPC_aligned:
16015 case OMPC_copyin:
16016 case OMPC_copyprivate:
16017 case OMPC_ordered:
16018 case OMPC_nowait:
16019 case OMPC_untied:
16020 case OMPC_mergeable:
16021 case OMPC_threadprivate:
16022 case OMPC_allocate:
16023 case OMPC_flush:
16024 case OMPC_depobj:
16025 case OMPC_read:
16026 case OMPC_write:
16027 case OMPC_update:
16028 case OMPC_capture:
16029 case OMPC_compare:
16030 case OMPC_seq_cst:
16031 case OMPC_acq_rel:
16032 case OMPC_acquire:
16033 case OMPC_release:
16034 case OMPC_relaxed:
16035 case OMPC_depend:
16036 case OMPC_threads:
16037 case OMPC_simd:
16038 case OMPC_map:
16039 case OMPC_nogroup:
16040 case OMPC_hint:
16041 case OMPC_defaultmap:
16042 case OMPC_unknown:
16043 case OMPC_uniform:
16044 case OMPC_to:
16045 case OMPC_from:
16046 case OMPC_use_device_ptr:
16047 case OMPC_use_device_addr:
16048 case OMPC_is_device_ptr:
16049 case OMPC_unified_address:
16050 case OMPC_unified_shared_memory:
16051 case OMPC_reverse_offload:
16052 case OMPC_dynamic_allocators:
16053 case OMPC_atomic_default_mem_order:
16054 case OMPC_device_type:
16055 case OMPC_match:
16056 case OMPC_nontemporal:
16057 case OMPC_order:
16058 case OMPC_destroy:
16059 case OMPC_detach:
16060 case OMPC_inclusive:
16061 case OMPC_exclusive:
16062 case OMPC_uses_allocators:
16063 case OMPC_affinity:
16064 case OMPC_bind:
16065 default:
16066 llvm_unreachable("Unexpected OpenMP clause.");
16067 }
16068 return CaptureRegion;
16069}
16070
16072 Expr *Condition, SourceLocation StartLoc,
16073 SourceLocation LParenLoc,
16074 SourceLocation NameModifierLoc,
16075 SourceLocation ColonLoc,
16076 SourceLocation EndLoc) {
16077 Expr *ValExpr = Condition;
16078 Stmt *HelperValStmt = nullptr;
16079 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16080 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16081 !Condition->isInstantiationDependent() &&
16082 !Condition->containsUnexpandedParameterPack()) {
16084 if (Val.isInvalid())
16085 return nullptr;
16086
16087 ValExpr = Val.get();
16088
16089 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16090 CaptureRegion = getOpenMPCaptureRegionForClause(
16091 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16092 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16093 ValExpr = MakeFullExpr(ValExpr).get();
16094 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16095 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16096 HelperValStmt = buildPreInits(Context, Captures);
16097 }
16098 }
16099
16100 return new (Context)
16101 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16102 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16103}
16104
16106 SourceLocation StartLoc,
16107 SourceLocation LParenLoc,
16108 SourceLocation EndLoc) {
16109 Expr *ValExpr = Condition;
16110 Stmt *HelperValStmt = nullptr;
16111 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16112 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16113 !Condition->isInstantiationDependent() &&
16114 !Condition->containsUnexpandedParameterPack()) {
16116 if (Val.isInvalid())
16117 return nullptr;
16118
16119 ValExpr = MakeFullExpr(Val.get()).get();
16120
16121 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16122 CaptureRegion =
16123 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16124 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16125 ValExpr = MakeFullExpr(ValExpr).get();
16126 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16127 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16128 HelperValStmt = buildPreInits(Context, Captures);
16129 }
16130 }
16131
16132 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16133 StartLoc, LParenLoc, EndLoc);
16134}
16135
16137 Expr *Op) {
16138 if (!Op)
16139 return ExprError();
16140
16141 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16142 public:
16143 IntConvertDiagnoser()
16144 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16145 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16146 QualType T) override {
16147 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16148 }
16149 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16150 QualType T) override {
16151 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16152 }
16153 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16154 QualType T,
16155 QualType ConvTy) override {
16156 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16157 }
16158 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16159 QualType ConvTy) override {
16160 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16161 << ConvTy->isEnumeralType() << ConvTy;
16162 }
16163 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16164 QualType T) override {
16165 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16166 }
16167 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16168 QualType ConvTy) override {
16169 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16170 << ConvTy->isEnumeralType() << ConvTy;
16171 }
16172 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16173 QualType) override {
16174 llvm_unreachable("conversion functions are permitted");
16175 }
16176 } ConvertDiagnoser;
16177 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16178}
16179
16180static bool
16182 bool StrictlyPositive, bool BuildCapture = false,
16183 OpenMPDirectiveKind DKind = OMPD_unknown,
16184 OpenMPDirectiveKind *CaptureRegion = nullptr,
16185 Stmt **HelperValStmt = nullptr) {
16186 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16187 !ValExpr->isInstantiationDependent()) {
16188 SourceLocation Loc = ValExpr->getExprLoc();
16190 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16191 if (Value.isInvalid())
16192 return false;
16193
16194 ValExpr = Value.get();
16195 // The expression must evaluate to a non-negative integer value.
16197 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16198 if (Result->isSigned() &&
16199 !((!StrictlyPositive && Result->isNonNegative()) ||
16200 (StrictlyPositive && Result->isStrictlyPositive()))) {
16201 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16202 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16203 << ValExpr->getSourceRange();
16204 return false;
16205 }
16206 }
16207 if (!BuildCapture)
16208 return true;
16209 *CaptureRegion =
16210 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16211 if (*CaptureRegion != OMPD_unknown &&
16212 !SemaRef.CurContext->isDependentContext()) {
16213 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16214 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16215 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16216 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16217 }
16218 }
16219 return true;
16220}
16221
16223 SourceLocation StartLoc,
16224 SourceLocation LParenLoc,
16225 SourceLocation EndLoc) {
16226 Expr *ValExpr = NumThreads;
16227 Stmt *HelperValStmt = nullptr;
16228
16229 // OpenMP [2.5, Restrictions]
16230 // The num_threads expression must evaluate to a positive integer value.
16231 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16232 /*StrictlyPositive=*/true))
16233 return nullptr;
16234
16235 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16236 OpenMPDirectiveKind CaptureRegion =
16237 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16238 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16239 ValExpr = MakeFullExpr(ValExpr).get();
16240 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16241 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16242 HelperValStmt = buildPreInits(Context, Captures);
16243 }
16244
16245 return new (Context) OMPNumThreadsClause(
16246 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16247}
16248
16249ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16250 OpenMPClauseKind CKind,
16251 bool StrictlyPositive,
16252 bool SuppressExprDiags) {
16253 if (!E)
16254 return ExprError();
16255 if (E->isValueDependent() || E->isTypeDependent() ||
16257 return E;
16258
16259 llvm::APSInt Result;
16260 ExprResult ICE;
16261 if (SuppressExprDiags) {
16262 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16263 // expression.
16264 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16265 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16266 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16267 SourceLocation Loc) override {
16268 llvm_unreachable("Diagnostic suppressed");
16269 }
16270 } Diagnoser;
16271 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16272 } else {
16273 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16274 }
16275 if (ICE.isInvalid())
16276 return ExprError();
16277
16278 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16279 (!StrictlyPositive && !Result.isNonNegative())) {
16280 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16281 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16282 << E->getSourceRange();
16283 return ExprError();
16284 }
16285 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16286 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16287 << E->getSourceRange();
16288 return ExprError();
16289 }
16290 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16291 DSAStack->setAssociatedLoops(Result.getExtValue());
16292 else if (CKind == OMPC_ordered)
16293 DSAStack->setAssociatedLoops(Result.getExtValue());
16294 return ICE;
16295}
16296
16298 SourceLocation LParenLoc,
16299 SourceLocation EndLoc) {
16300 // OpenMP [2.8.1, simd construct, Description]
16301 // The parameter of the safelen clause must be a constant
16302 // positive integer expression.
16303 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16304 if (Safelen.isInvalid())
16305 return nullptr;
16306 return new (Context)
16307 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16308}
16309
16311 SourceLocation LParenLoc,
16312 SourceLocation EndLoc) {
16313 // OpenMP [2.8.1, simd construct, Description]
16314 // The parameter of the simdlen clause must be a constant
16315 // positive integer expression.
16316 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16317 if (Simdlen.isInvalid())
16318 return nullptr;
16319 return new (Context)
16320 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16321}
16322
16323/// Tries to find omp_allocator_handle_t type.
16325 DSAStackTy *Stack) {
16326 QualType OMPAllocatorHandleT = Stack->getOMPAllocatorHandleT();
16327 if (!OMPAllocatorHandleT.isNull())
16328 return true;
16329 // Build the predefined allocator expressions.
16330 bool ErrorFound = false;
16331 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16332 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16333 StringRef Allocator =
16334 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16335 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16336 auto *VD = dyn_cast_or_null<ValueDecl>(
16337 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16338 if (!VD) {
16339 ErrorFound = true;
16340 break;
16341 }
16342 QualType AllocatorType =
16344 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16345 if (!Res.isUsable()) {
16346 ErrorFound = true;
16347 break;
16348 }
16349 if (OMPAllocatorHandleT.isNull())
16350 OMPAllocatorHandleT = AllocatorType;
16351 if (!S.getASTContext().hasSameType(OMPAllocatorHandleT, AllocatorType)) {
16352 ErrorFound = true;
16353 break;
16354 }
16355 Stack->setAllocator(AllocatorKind, Res.get());
16356 }
16357 if (ErrorFound) {
16358 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16359 << "omp_allocator_handle_t";
16360 return false;
16361 }
16362 OMPAllocatorHandleT.addConst();
16363 Stack->setOMPAllocatorHandleT(OMPAllocatorHandleT);
16364 return true;
16365}
16366
16368 SourceLocation LParenLoc,
16369 SourceLocation EndLoc) {
16370 // OpenMP [2.11.3, allocate Directive, Description]
16371 // allocator is an expression of omp_allocator_handle_t type.
16372 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStack))
16373 return nullptr;
16374
16375 ExprResult Allocator = DefaultLvalueConversion(A);
16376 if (Allocator.isInvalid())
16377 return nullptr;
16378 Allocator = PerformImplicitConversion(Allocator.get(),
16379 DSAStack->getOMPAllocatorHandleT(),
16381 /*AllowExplicit=*/true);
16382 if (Allocator.isInvalid())
16383 return nullptr;
16384 return new (Context)
16385 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16386}
16387
16389 SourceLocation StartLoc,
16390 SourceLocation LParenLoc,
16391 SourceLocation EndLoc) {
16392 // OpenMP [2.7.1, loop construct, Description]
16393 // OpenMP [2.8.1, simd construct, Description]
16394 // OpenMP [2.9.6, distribute construct, Description]
16395 // The parameter of the collapse clause must be a constant
16396 // positive integer expression.
16397 ExprResult NumForLoopsResult =
16398 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16399 if (NumForLoopsResult.isInvalid())
16400 return nullptr;
16401 return new (Context)
16402 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16403}
16404
16406 SourceLocation EndLoc,
16407 SourceLocation LParenLoc,
16408 Expr *NumForLoops) {
16409 // OpenMP [2.7.1, loop construct, Description]
16410 // OpenMP [2.8.1, simd construct, Description]
16411 // OpenMP [2.9.6, distribute construct, Description]
16412 // The parameter of the ordered clause must be a constant
16413 // positive integer expression if any.
16414 if (NumForLoops && LParenLoc.isValid()) {
16415 ExprResult NumForLoopsResult =
16416 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16417 if (NumForLoopsResult.isInvalid())
16418 return nullptr;
16419 NumForLoops = NumForLoopsResult.get();
16420 } else {
16421 NumForLoops = nullptr;
16422 }
16423 auto *Clause = OMPOrderedClause::Create(
16424 Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16425 StartLoc, LParenLoc, EndLoc);
16426 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16427 return Clause;
16428}
16429
16431 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16432 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16433 OMPClause *Res = nullptr;
16434 switch (Kind) {
16435 case OMPC_default:
16436 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16437 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16438 break;
16439 case OMPC_proc_bind:
16440 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16441 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16442 break;
16443 case OMPC_atomic_default_mem_order:
16445 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16446 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16447 break;
16448 case OMPC_order:
16449 Res = ActOnOpenMPOrderClause(static_cast<OpenMPOrderClauseKind>(Argument),
16450 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16451 break;
16452 case OMPC_update:
16453 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16454 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16455 break;
16456 case OMPC_bind:
16457 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16458 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16459 break;
16460 case OMPC_if:
16461 case OMPC_final:
16462 case OMPC_num_threads:
16463 case OMPC_safelen:
16464 case OMPC_simdlen:
16465 case OMPC_sizes:
16466 case OMPC_allocator:
16467 case OMPC_collapse:
16468 case OMPC_schedule:
16469 case OMPC_private:
16470 case OMPC_firstprivate:
16471 case OMPC_lastprivate:
16472 case OMPC_shared:
16473 case OMPC_reduction:
16474 case OMPC_task_reduction:
16475 case OMPC_in_reduction:
16476 case OMPC_linear:
16477 case OMPC_aligned:
16478 case OMPC_copyin:
16479 case OMPC_copyprivate:
16480 case OMPC_ordered:
16481 case OMPC_nowait:
16482 case OMPC_untied:
16483 case OMPC_mergeable:
16484 case OMPC_threadprivate:
16485 case OMPC_allocate:
16486 case OMPC_flush:
16487 case OMPC_depobj:
16488 case OMPC_read:
16489 case OMPC_write:
16490 case OMPC_capture:
16491 case OMPC_compare:
16492 case OMPC_seq_cst:
16493 case OMPC_acq_rel:
16494 case OMPC_acquire:
16495 case OMPC_release:
16496 case OMPC_relaxed:
16497 case OMPC_depend:
16498 case OMPC_device:
16499 case OMPC_threads:
16500 case OMPC_simd:
16501 case OMPC_map:
16502 case OMPC_num_teams:
16503 case OMPC_thread_limit:
16504 case OMPC_priority:
16505 case OMPC_grainsize:
16506 case OMPC_nogroup:
16507 case OMPC_num_tasks:
16508 case OMPC_hint:
16509 case OMPC_dist_schedule:
16510 case OMPC_defaultmap:
16511 case OMPC_unknown:
16512 case OMPC_uniform:
16513 case OMPC_to:
16514 case OMPC_from:
16515 case OMPC_use_device_ptr:
16516 case OMPC_use_device_addr:
16517 case OMPC_is_device_ptr:
16518 case OMPC_has_device_addr:
16519 case OMPC_unified_address:
16520 case OMPC_unified_shared_memory:
16521 case OMPC_reverse_offload:
16522 case OMPC_dynamic_allocators:
16523 case OMPC_device_type:
16524 case OMPC_match:
16525 case OMPC_nontemporal:
16526 case OMPC_destroy:
16527 case OMPC_novariants:
16528 case OMPC_nocontext:
16529 case OMPC_detach:
16530 case OMPC_inclusive:
16531 case OMPC_exclusive:
16532 case OMPC_uses_allocators:
16533 case OMPC_affinity:
16534 case OMPC_when:
16535 default:
16536 llvm_unreachable("Clause is not allowed.");
16537 }
16538 return Res;
16539}
16540
16541static std::string
16543 ArrayRef<unsigned> Exclude = llvm::None) {
16544 SmallString<256> Buffer;
16545 llvm::raw_svector_ostream Out(Buffer);
16546 unsigned Skipped = Exclude.size();
16547 auto S = Exclude.begin(), E = Exclude.end();
16548 for (unsigned I = First; I < Last; ++I) {
16549 if (std::find(S, E, I) != E) {
16550 --Skipped;
16551 continue;
16552 }
16553 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16554 if (I + Skipped + 2 == Last)
16555 Out << " or ";
16556 else if (I + Skipped + 1 != Last)
16557 Out << ", ";
16558 }
16559 return std::string(Out.str());
16560}
16561
16563 SourceLocation KindKwLoc,
16564 SourceLocation StartLoc,
16565 SourceLocation LParenLoc,
16566 SourceLocation EndLoc) {
16567 if (Kind == OMP_DEFAULT_unknown) {
16568 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16569 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16570 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16571 << getOpenMPClauseName(OMPC_default);
16572 return nullptr;
16573 }
16574
16575 switch (Kind) {
16576 case OMP_DEFAULT_none:
16577 DSAStack->setDefaultDSANone(KindKwLoc);
16578 break;
16579 case OMP_DEFAULT_shared:
16580 DSAStack->setDefaultDSAShared(KindKwLoc);
16581 break;
16582 case OMP_DEFAULT_firstprivate:
16583 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16584 break;
16585 case OMP_DEFAULT_private:
16586 DSAStack->setDefaultDSAPrivate(KindKwLoc);
16587 break;
16588 default:
16589 llvm_unreachable("DSA unexpected in OpenMP default clause");
16590 }
16591
16592 return new (Context)
16593 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16594}
16595
16597 SourceLocation KindKwLoc,
16598 SourceLocation StartLoc,
16599 SourceLocation LParenLoc,
16600 SourceLocation EndLoc) {
16601 if (Kind == OMP_PROC_BIND_unknown) {
16602 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16603 << getListOfPossibleValues(OMPC_proc_bind,
16604 /*First=*/unsigned(OMP_PROC_BIND_master),
16605 /*Last=*/
16606 unsigned(LangOpts.OpenMP > 50
16607 ? OMP_PROC_BIND_primary
16608 : OMP_PROC_BIND_spread) +
16609 1)
16610 << getOpenMPClauseName(OMPC_proc_bind);
16611 return nullptr;
16612 }
16613 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
16614 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16615 << getListOfPossibleValues(OMPC_proc_bind,
16616 /*First=*/unsigned(OMP_PROC_BIND_master),
16617 /*Last=*/
16618 unsigned(OMP_PROC_BIND_spread) + 1)
16619 << getOpenMPClauseName(OMPC_proc_bind);
16620 return new (Context)
16621 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16622}
16623
16626 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16628 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16630 OMPC_atomic_default_mem_order, /*First=*/0,
16632 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
16633 return nullptr;
16634 }
16635 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
16636 LParenLoc, EndLoc);
16637}
16638
16640 SourceLocation KindKwLoc,
16641 SourceLocation StartLoc,
16642 SourceLocation LParenLoc,
16643 SourceLocation EndLoc) {
16644 if (Kind == OMPC_ORDER_unknown) {
16645 static_assert(OMPC_ORDER_unknown > 0,
16646 "OMPC_ORDER_unknown not greater than 0");
16647 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16648 << getListOfPossibleValues(OMPC_order, /*First=*/0,
16649 /*Last=*/OMPC_ORDER_unknown)
16650 << getOpenMPClauseName(OMPC_order);
16651 return nullptr;
16652 }
16653 return new (Context)
16654 OMPOrderClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16655}
16656
16658 SourceLocation KindKwLoc,
16659 SourceLocation StartLoc,
16660 SourceLocation LParenLoc,
16661 SourceLocation EndLoc) {
16662 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16663 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16664 SmallVector<unsigned> Except = {
16665 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16666 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16667 if (LangOpts.OpenMP < 51)
16668 Except.push_back(OMPC_DEPEND_inoutset);
16669 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16670 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16671 /*Last=*/OMPC_DEPEND_unknown, Except)
16672 << getOpenMPClauseName(OMPC_update);
16673 return nullptr;
16674 }
16675 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
16676 EndLoc);
16677}
16678
16680 SourceLocation StartLoc,
16681 SourceLocation LParenLoc,
16682 SourceLocation EndLoc) {
16683 for (Expr *SizeExpr : SizeExprs) {
16684 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
16685 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
16686 if (!NumForLoopsResult.isUsable())
16687 return nullptr;
16688 }
16689
16690 DSAStack->setAssociatedLoops(SizeExprs.size());
16691 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16692 SizeExprs);
16693}
16694
16696 SourceLocation EndLoc) {
16697 return OMPFullClause::Create(Context, StartLoc, EndLoc);
16698}
16699
16701 SourceLocation StartLoc,
16702 SourceLocation LParenLoc,
16703 SourceLocation EndLoc) {
16704 if (FactorExpr) {
16705 // If an argument is specified, it must be a constant (or an unevaluated
16706 // template expression).
16707 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16708 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16709 if (FactorResult.isInvalid())
16710 return nullptr;
16711 FactorExpr = FactorResult.get();
16712 }
16713
16714 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16715 FactorExpr);
16716}
16717
16719 SourceLocation LParenLoc,
16720 SourceLocation EndLoc) {
16721 ExprResult AlignVal;
16722 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16723 if (AlignVal.isInvalid())
16724 return nullptr;
16725 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
16726 EndLoc);
16727}
16728
16731 SourceLocation StartLoc, SourceLocation LParenLoc,
16732 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16733 SourceLocation EndLoc) {
16734 OMPClause *Res = nullptr;
16735 switch (Kind) {
16736 case OMPC_schedule:
16737 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16738 assert(Argument.size() == NumberOfElements &&
16739 ArgumentLoc.size() == NumberOfElements);
16741 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16742 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16743 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16744 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16745 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16746 break;
16747 case OMPC_if:
16748 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16749 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16750 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16751 DelimLoc, EndLoc);
16752 break;
16753 case OMPC_dist_schedule:
16755 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16756 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16757 break;
16758 case OMPC_defaultmap:
16759 enum { Modifier, DefaultmapKind };
16761 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16762 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16763 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16764 EndLoc);
16765 break;
16766 case OMPC_device:
16767 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16769 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16770 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16771 break;
16772 case OMPC_final:
16773 case OMPC_num_threads:
16774 case OMPC_safelen:
16775 case OMPC_simdlen:
16776 case OMPC_sizes:
16777 case OMPC_allocator:
16778 case OMPC_collapse:
16779 case OMPC_default:
16780 case OMPC_proc_bind:
16781 case OMPC_private:
16782 case OMPC_firstprivate:
16783 case OMPC_lastprivate:
16784 case OMPC_shared:
16785 case OMPC_reduction:
16786 case OMPC_task_reduction:
16787 case OMPC_in_reduction:
16788 case OMPC_linear:
16789 case OMPC_aligned:
16790 case OMPC_copyin:
16791 case OMPC_copyprivate:
16792 case OMPC_ordered:
16793 case OMPC_nowait:
16794 case OMPC_untied:
16795 case OMPC_mergeable:
16796 case OMPC_threadprivate:
16797 case OMPC_allocate:
16798 case OMPC_flush:
16799 case OMPC_depobj:
16800 case OMPC_read:
16801 case OMPC_write:
16802 case OMPC_update:
16803 case OMPC_capture:
16804 case OMPC_compare:
16805 case OMPC_seq_cst:
16806 case OMPC_acq_rel:
16807 case OMPC_acquire:
16808 case OMPC_release:
16809 case OMPC_relaxed:
16810 case OMPC_depend:
16811 case OMPC_threads:
16812 case OMPC_simd:
16813 case OMPC_map:
16814 case OMPC_num_teams:
16815 case OMPC_thread_limit:
16816 case OMPC_priority:
16817 case OMPC_grainsize:
16818 case OMPC_nogroup:
16819 case OMPC_num_tasks:
16820 case OMPC_hint:
16821 case OMPC_unknown:
16822 case OMPC_uniform:
16823 case OMPC_to:
16824 case OMPC_from:
16825 case OMPC_use_device_ptr:
16826 case OMPC_use_device_addr:
16827 case OMPC_is_device_ptr:
16828 case OMPC_has_device_addr:
16829 case OMPC_unified_address:
16830 case OMPC_unified_shared_memory:
16831 case OMPC_reverse_offload:
16832 case OMPC_dynamic_allocators:
16833 case OMPC_atomic_default_mem_order:
16834 case OMPC_device_type:
16835 case OMPC_match:
16836 case OMPC_nontemporal:
16837 case OMPC_order:
16838 case OMPC_destroy:
16839 case OMPC_novariants:
16840 case OMPC_nocontext:
16841 case OMPC_detach:
16842 case OMPC_inclusive:
16843 case OMPC_exclusive:
16844 case OMPC_uses_allocators:
16845 case OMPC_affinity:
16846 case OMPC_when:
16847 case OMPC_bind:
16848 default:
16849 llvm_unreachable("Clause is not allowed.");
16850 }
16851 return Res;
16852}
16853
16856 SourceLocation M1Loc, SourceLocation M2Loc) {
16857 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16858 SmallVector<unsigned, 2> Excluded;
16860 Excluded.push_back(M2);
16861 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16862 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16863 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16864 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16865 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16866 << getListOfPossibleValues(OMPC_schedule,
16867 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16869 Excluded)
16870 << getOpenMPClauseName(OMPC_schedule);
16871 return true;
16872 }
16873 return false;
16874}
16875
16878 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16879 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16880 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16881 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
16882 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
16883 return nullptr;
16884 // OpenMP, 2.7.1, Loop Construct, Restrictions
16885 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16886 // but not both.
16887 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16888 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16889 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16890 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16891 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16892 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16893 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16894 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16895 return nullptr;
16896 }
16897 if (Kind == OMPC_SCHEDULE_unknown) {
16898 std::string Values;
16899 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16900 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16901 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16903 Exclude);
16904 } else {
16905 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16906 /*Last=*/OMPC_SCHEDULE_unknown);
16907 }
16908 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16909 << Values << getOpenMPClauseName(OMPC_schedule);
16910 return nullptr;
16911 }
16912 // OpenMP, 2.7.1, Loop Construct, Restrictions
16913 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16914 // schedule(guided).
16915 // OpenMP 5.0 does not have this restriction.
16916 if (LangOpts.OpenMP < 50 &&
16917 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16918 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16919 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16920 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16921 diag::err_omp_schedule_nonmonotonic_static);
16922 return nullptr;
16923 }
16924 Expr *ValExpr = ChunkSize;
16925 Stmt *HelperValStmt = nullptr;
16926 if (ChunkSize) {
16927 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16928 !ChunkSize->isInstantiationDependent() &&
16929 !ChunkSize->containsUnexpandedParameterPack()) {
16930 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16931 ExprResult Val =
16932 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16933 if (Val.isInvalid())
16934 return nullptr;
16935
16936 ValExpr = Val.get();
16937
16938 // OpenMP [2.7.1, Restrictions]
16939 // chunk_size must be a loop invariant integer expression with a positive
16940 // value.
16942 ValExpr->getIntegerConstantExpr(Context)) {
16943 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16944 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16945 << "schedule" << 1 << ChunkSize->getSourceRange();
16946 return nullptr;
16947 }
16949 DSAStack->getCurrentDirective(), OMPC_schedule,
16950 LangOpts.OpenMP) != OMPD_unknown &&
16952 ValExpr = MakeFullExpr(ValExpr).get();
16953 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16954 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16955 HelperValStmt = buildPreInits(Context, Captures);
16956 }
16957 }
16958 }
16959
16960 return new (Context)
16961 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16962 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16963}
16964
16966 SourceLocation StartLoc,
16967 SourceLocation EndLoc) {
16968 OMPClause *Res = nullptr;
16969 switch (Kind) {
16970 case OMPC_ordered:
16971 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16972 break;
16973 case OMPC_nowait:
16974 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16975 break;
16976 case OMPC_untied:
16977 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16978 break;
16979 case OMPC_mergeable:
16980 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16981 break;
16982 case OMPC_read:
16983 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16984 break;
16985 case OMPC_write:
16986 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16987 break;
16988 case OMPC_update:
16989 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16990 break;
16991 case OMPC_capture:
16992 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16993 break;
16994 case OMPC_compare:
16995 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16996 break;
16997 case OMPC_seq_cst:
16998 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16999 break;
17000 case OMPC_acq_rel:
17001 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17002 break;
17003 case OMPC_acquire:
17004 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17005 break;
17006 case OMPC_release:
17007 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17008 break;
17009 case OMPC_relaxed:
17010 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17011 break;
17012 case OMPC_threads:
17013 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17014 break;
17015 case OMPC_simd:
17016 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17017 break;
17018 case OMPC_nogroup:
17019 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17020 break;
17021 case OMPC_unified_address:
17022 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17023 break;
17024 case OMPC_unified_shared_memory:
17025 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17026 break;
17027 case OMPC_reverse_offload:
17028 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17029 break;
17030 case OMPC_dynamic_allocators:
17031 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17032 break;
17033 case OMPC_destroy:
17034 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17035 /*LParenLoc=*/SourceLocation(),
17036 /*VarLoc=*/SourceLocation(), EndLoc);
17037 break;
17038 case OMPC_full:
17039 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17040 break;
17041 case OMPC_partial:
17042 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17043 break;
17044 case OMPC_if:
17045 case OMPC_final:
17046 case OMPC_num_threads:
17047 case OMPC_safelen:
17048 case OMPC_simdlen:
17049 case OMPC_sizes:
17050 case OMPC_allocator:
17051 case OMPC_collapse:
17052 case OMPC_schedule:
17053 case OMPC_private:
17054 case OMPC_firstprivate:
17055 case OMPC_lastprivate:
17056 case OMPC_shared:
17057 case OMPC_reduction:
17058 case OMPC_task_reduction:
17059 case OMPC_in_reduction:
17060 case OMPC_linear:
17061 case OMPC_aligned:
17062 case OMPC_copyin:
17063 case OMPC_copyprivate:
17064 case OMPC_default:
17065 case OMPC_proc_bind:
17066 case OMPC_threadprivate:
17067 case OMPC_allocate:
17068 case OMPC_flush:
17069 case OMPC_depobj:
17070 case OMPC_depend:
17071 case OMPC_device:
17072 case OMPC_map:
17073 case OMPC_num_teams:
17074 case OMPC_thread_limit:
17075 case OMPC_priority:
17076 case OMPC_grainsize:
17077 case OMPC_num_tasks:
17078 case OMPC_hint:
17079 case OMPC_dist_schedule:
17080 case OMPC_defaultmap:
17081 case OMPC_unknown:
17082 case OMPC_uniform:
17083 case OMPC_to:
17084 case OMPC_from:
17085 case OMPC_use_device_ptr:
17086 case OMPC_use_device_addr:
17087 case OMPC_is_device_ptr:
17088 case OMPC_has_device_addr:
17089 case OMPC_atomic_default_mem_order:
17090 case OMPC_device_type:
17091 case OMPC_match:
17092 case OMPC_nontemporal:
17093 case OMPC_order:
17094 case OMPC_novariants:
17095 case OMPC_nocontext:
17096 case OMPC_detach:
17097 case OMPC_inclusive:
17098 case OMPC_exclusive:
17099 case OMPC_uses_allocators:
17100 case OMPC_affinity:
17101 case OMPC_when:
17102 default:
17103 llvm_unreachable("Clause is not allowed.");
17104 }
17105 return Res;
17106}
17107
17109 SourceLocation EndLoc) {
17110 DSAStack->setNowaitRegion();
17111 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17112}
17113
17115 SourceLocation EndLoc) {
17116 DSAStack->setUntiedRegion();
17117 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17118}
17119
17121 SourceLocation EndLoc) {
17122 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17123}
17124
17126 SourceLocation EndLoc) {
17127 return new (Context) OMPReadClause(StartLoc, EndLoc);
17128}
17129
17131 SourceLocation EndLoc) {
17132 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17133}
17134
17136 SourceLocation EndLoc) {
17137 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17138}
17139
17141 SourceLocation EndLoc) {
17142 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17143}
17144
17146 SourceLocation EndLoc) {
17147 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17148}
17149
17151 SourceLocation EndLoc) {
17152 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17153}
17154
17156 SourceLocation EndLoc) {
17157 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17158}
17159
17161 SourceLocation EndLoc) {
17162 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17163}
17164
17166 SourceLocation EndLoc) {
17167 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17168}
17169
17171 SourceLocation EndLoc) {
17172 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17173}
17174
17176 SourceLocation EndLoc) {
17177 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17178}
17179
17181 SourceLocation EndLoc) {
17182 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17183}
17184
17186 SourceLocation EndLoc) {
17187 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17188}
17189
17191 SourceLocation EndLoc) {
17192 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17193}
17194
17199
17201 SourceLocation EndLoc) {
17202 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17203}
17204
17206 SourceLocation EndLoc) {
17207 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17208}
17209
17211 SourceLocation StartLoc,
17212 SourceLocation EndLoc) {
17213
17214 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17215 // At least one action-clause must appear on a directive.
17216 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17217 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17218 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17219 << Expected << getOpenMPDirectiveName(OMPD_interop);
17220 return StmtError();
17221 }
17222
17223 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17224 // A depend clause can only appear on the directive if a targetsync
17225 // interop-type is present or the interop-var was initialized with
17226 // the targetsync interop-type.
17227
17228 // If there is any 'init' clause diagnose if there is no 'init' clause with
17229 // interop-type of 'targetsync'. Cases involving other directives cannot be
17230 // diagnosed.
17231 const OMPDependClause *DependClause = nullptr;
17232 bool HasInitClause = false;
17233 bool IsTargetSync = false;
17234 for (const OMPClause *C : Clauses) {
17235 if (IsTargetSync)
17236 break;
17237 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17238 HasInitClause = true;
17239 if (InitClause->getIsTargetSync())
17240 IsTargetSync = true;
17241 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17242 DependClause = DC;
17243 }
17244 }
17245 if (DependClause && HasInitClause && !IsTargetSync) {
17246 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17247 return StmtError();
17248 }
17249
17250 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17251 // Each interop-var may be specified for at most one action-clause of each
17252 // interop construct.
17254 for (const OMPClause *C : Clauses) {
17255 OpenMPClauseKind ClauseKind = C->getClauseKind();
17256 const DeclRefExpr *DRE = nullptr;
17257 SourceLocation VarLoc;
17258
17259 if (ClauseKind == OMPC_init) {
17260 const auto *IC = cast<OMPInitClause>(C);
17261 VarLoc = IC->getVarLoc();
17262 DRE = dyn_cast_or_null<DeclRefExpr>(IC->getInteropVar());
17263 } else if (ClauseKind == OMPC_use) {
17264 const auto *UC = cast<OMPUseClause>(C);
17265 VarLoc = UC->getVarLoc();
17266 DRE = dyn_cast_or_null<DeclRefExpr>(UC->getInteropVar());
17267 } else if (ClauseKind == OMPC_destroy) {
17268 const auto *DC = cast<OMPDestroyClause>(C);
17269 VarLoc = DC->getVarLoc();
17270 DRE = dyn_cast_or_null<DeclRefExpr>(DC->getInteropVar());
17271 }
17272
17273 if (!DRE)
17274 continue;
17275
17276 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
17277 if (!InteropVars.insert(VD->getCanonicalDecl()).second) {
17278 Diag(VarLoc, diag::err_omp_interop_var_multiple_actions) << VD;
17279 return StmtError();
17280 }
17281 }
17282 }
17283
17284 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17285}
17286
17287static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17288 SourceLocation VarLoc,
17289 OpenMPClauseKind Kind) {
17290 if (InteropVarExpr->isValueDependent() || InteropVarExpr->isTypeDependent() ||
17291 InteropVarExpr->isInstantiationDependent() ||
17292 InteropVarExpr->containsUnexpandedParameterPack())
17293 return true;
17294
17295 const auto *DRE = dyn_cast<DeclRefExpr>(InteropVarExpr);
17296 if (!DRE || !isa<VarDecl>(DRE->getDecl())) {
17297 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) << 0;
17298 return false;
17299 }
17300
17301 // Interop variable should be of type omp_interop_t.
17302 bool HasError = false;
17303 QualType InteropType;
17304 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17305 VarLoc, Sema::LookupOrdinaryName);
17306 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17307 NamedDecl *ND = Result.getFoundDecl();
17308 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17309 InteropType = QualType(TD->getTypeForDecl(), 0);
17310 } else {
17311 HasError = true;
17312 }
17313 } else {
17314 HasError = true;
17315 }
17316
17317 if (HasError) {
17318 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17319 << "omp_interop_t";
17320 return false;
17321 }
17322
17323 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17324 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17325 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17326 return false;
17327 }
17328
17329 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17330 // The interop-var passed to init or destroy must be non-const.
17331 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17332 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17333 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17334 << /*non-const*/ 1;
17335 return false;
17336 }
17337 return true;
17338}
17339
17340OMPClause *
17342 bool IsTarget, bool IsTargetSync,
17343 SourceLocation StartLoc, SourceLocation LParenLoc,
17344 SourceLocation VarLoc, SourceLocation EndLoc) {
17345
17346 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17347 return nullptr;
17348
17349 // Check prefer_type values. These foreign-runtime-id values are either
17350 // string literals or constant integral expressions.
17351 for (const Expr *E : PrefExprs) {
17352 if (E->isValueDependent() || E->isTypeDependent() ||
17354 continue;
17356 continue;
17357 if (isa<StringLiteral>(E))
17358 continue;
17359 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17360 return nullptr;
17361 }
17362
17363 return OMPInitClause::Create(Context, InteropVar, PrefExprs, IsTarget,
17364 IsTargetSync, StartLoc, LParenLoc, VarLoc,
17365 EndLoc);
17366}
17367
17369 SourceLocation LParenLoc,
17370 SourceLocation VarLoc,
17371 SourceLocation EndLoc) {
17372
17373 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
17374 return nullptr;
17375
17376 return new (Context)
17377 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17378}
17379
17381 SourceLocation StartLoc,
17382 SourceLocation LParenLoc,
17383 SourceLocation VarLoc,
17384 SourceLocation EndLoc) {
17385 if (InteropVar &&
17386 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
17387 return nullptr;
17388
17389 return new (Context)
17390 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17391}
17392
17394 SourceLocation StartLoc,
17395 SourceLocation LParenLoc,
17396 SourceLocation EndLoc) {
17397 Expr *ValExpr = Condition;
17398 Stmt *HelperValStmt = nullptr;
17399 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17400 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17401 !Condition->isInstantiationDependent() &&
17402 !Condition->containsUnexpandedParameterPack()) {
17404 if (Val.isInvalid())
17405 return nullptr;
17406
17407 ValExpr = MakeFullExpr(Val.get()).get();
17408
17409 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17410 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17411 LangOpts.OpenMP);
17412 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17413 ValExpr = MakeFullExpr(ValExpr).get();
17414 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17415 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17416 HelperValStmt = buildPreInits(Context, Captures);
17417 }
17418 }
17419
17420 return new (Context) OMPNovariantsClause(
17421 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17422}
17423
17425 SourceLocation StartLoc,
17426 SourceLocation LParenLoc,
17427 SourceLocation EndLoc) {
17428 Expr *ValExpr = Condition;
17429 Stmt *HelperValStmt = nullptr;
17430 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17431 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17432 !Condition->isInstantiationDependent() &&
17433 !Condition->containsUnexpandedParameterPack()) {
17435 if (Val.isInvalid())
17436 return nullptr;
17437
17438 ValExpr = MakeFullExpr(Val.get()).get();
17439
17440 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17441 CaptureRegion =
17442 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
17443 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17444 ValExpr = MakeFullExpr(ValExpr).get();
17445 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17446 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17447 HelperValStmt = buildPreInits(Context, Captures);
17448 }
17449 }
17450
17451 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
17452 StartLoc, LParenLoc, EndLoc);
17453}
17454
17456 SourceLocation StartLoc,
17457 SourceLocation LParenLoc,
17458 SourceLocation EndLoc) {
17459 Expr *ValExpr = ThreadID;
17460 Stmt *HelperValStmt = nullptr;
17461
17462 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17463 OpenMPDirectiveKind CaptureRegion =
17464 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
17465 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17466 ValExpr = MakeFullExpr(ValExpr).get();
17467 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17468 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17469 HelperValStmt = buildPreInits(Context, Captures);
17470 }
17471
17472 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
17473 StartLoc, LParenLoc, EndLoc);
17474}
17475
17477 ArrayRef<Expr *> VarList,
17478 const OMPVarListLocTy &Locs,
17479 OpenMPVarListDataTy &Data) {
17480 SourceLocation StartLoc = Locs.StartLoc;
17481 SourceLocation LParenLoc = Locs.LParenLoc;
17482 SourceLocation EndLoc = Locs.EndLoc;
17483 OMPClause *Res = nullptr;
17484 int ExtraModifier = Data.ExtraModifier;
17485 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17486 SourceLocation ColonLoc = Data.ColonLoc;
17487 switch (Kind) {
17488 case OMPC_private:
17489 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17490 break;
17491 case OMPC_firstprivate:
17492 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17493 break;
17494 case OMPC_lastprivate:
17495 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17496 "Unexpected lastprivate modifier.");
17498 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17499 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17500 break;
17501 case OMPC_shared:
17502 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17503 break;
17504 case OMPC_reduction:
17505 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17506 "Unexpected lastprivate modifier.");
17508 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17509 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17511 break;
17512 case OMPC_task_reduction:
17514 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17516 break;
17517 case OMPC_in_reduction:
17519 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17521 break;
17522 case OMPC_linear:
17523 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17524 "Unexpected linear modifier.");
17526 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17527 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17528 ColonLoc, EndLoc);
17529 break;
17530 case OMPC_aligned:
17531 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17532 LParenLoc, ColonLoc, EndLoc);
17533 break;
17534 case OMPC_copyin:
17535 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17536 break;
17537 case OMPC_copyprivate:
17538 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17539 break;
17540 case OMPC_flush:
17541 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17542 break;
17543 case OMPC_depend:
17544 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17545 "Unexpected depend modifier.");
17547 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17548 ColonLoc, Data.OmpAllMemoryLoc},
17549 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17550 break;
17551 case OMPC_map:
17552 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17553 "Unexpected map modifier.");
17557 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17558 ExtraModifierLoc, ColonLoc, VarList, Locs);
17559 break;
17560 case OMPC_to:
17561 Res =
17564 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17565 break;
17566 case OMPC_from:
17569 Data.ReductionOrMapperId, ColonLoc, VarList,
17570 Locs);
17571 break;
17572 case OMPC_use_device_ptr:
17573 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17574 break;
17575 case OMPC_use_device_addr:
17576 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17577 break;
17578 case OMPC_is_device_ptr:
17579 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17580 break;
17581 case OMPC_has_device_addr:
17582 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17583 break;
17584 case OMPC_allocate:
17585 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
17586 LParenLoc, ColonLoc, EndLoc);
17587 break;
17588 case OMPC_nontemporal:
17589 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17590 break;
17591 case OMPC_inclusive:
17592 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17593 break;
17594 case OMPC_exclusive:
17595 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17596 break;
17597 case OMPC_affinity:
17598 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17599 Data.DepModOrTailExpr, VarList);
17600 break;
17601 case OMPC_if:
17602 case OMPC_depobj:
17603 case OMPC_final:
17604 case OMPC_num_threads:
17605 case OMPC_safelen:
17606 case OMPC_simdlen:
17607 case OMPC_sizes:
17608 case OMPC_allocator:
17609 case OMPC_collapse:
17610 case OMPC_default:
17611 case OMPC_proc_bind:
17612 case OMPC_schedule:
17613 case OMPC_ordered:
17614 case OMPC_nowait:
17615 case OMPC_untied:
17616 case OMPC_mergeable:
17617 case OMPC_threadprivate:
17618 case OMPC_read:
17619 case OMPC_write:
17620 case OMPC_update:
17621 case OMPC_capture:
17622 case OMPC_compare:
17623 case OMPC_seq_cst:
17624 case OMPC_acq_rel:
17625 case OMPC_acquire:
17626 case OMPC_release:
17627 case OMPC_relaxed:
17628 case OMPC_device:
17629 case OMPC_threads:
17630 case OMPC_simd:
17631 case OMPC_num_teams:
17632 case OMPC_thread_limit:
17633 case OMPC_priority:
17634 case OMPC_grainsize:
17635 case OMPC_nogroup:
17636 case OMPC_num_tasks:
17637 case OMPC_hint:
17638 case OMPC_dist_schedule:
17639 case OMPC_defaultmap:
17640 case OMPC_unknown:
17641 case OMPC_uniform:
17642 case OMPC_unified_address:
17643 case OMPC_unified_shared_memory:
17644 case OMPC_reverse_offload:
17645 case OMPC_dynamic_allocators:
17646 case OMPC_atomic_default_mem_order:
17647 case OMPC_device_type:
17648 case OMPC_match:
17649 case OMPC_order:
17650 case OMPC_destroy:
17651 case OMPC_novariants:
17652 case OMPC_nocontext:
17653 case OMPC_detach:
17654 case OMPC_uses_allocators:
17655 case OMPC_when:
17656 case OMPC_bind:
17657 default:
17658 llvm_unreachable("Clause is not allowed.");
17659 }
17660 return Res;
17661}
17662
17666 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17667 if (!Res.isUsable())
17668 return ExprError();
17669 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17670 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17671 if (!Res.isUsable())
17672 return ExprError();
17673 }
17674 if (VK != VK_LValue && Res.get()->isGLValue()) {
17675 Res = DefaultLvalueConversion(Res.get());
17676 if (!Res.isUsable())
17677 return ExprError();
17678 }
17679 return Res;
17680}
17681
17683 SourceLocation StartLoc,
17684 SourceLocation LParenLoc,
17685 SourceLocation EndLoc) {
17687 SmallVector<Expr *, 8> PrivateCopies;
17688 bool IsImplicitClause =
17689 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17690 for (Expr *RefExpr : VarList) {
17691 assert(RefExpr && "NULL expr in OpenMP private clause.");
17692 SourceLocation ELoc;
17693 SourceRange ERange;
17694 Expr *SimpleRefExpr = RefExpr;
17695 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
17696 if (Res.second) {
17697 // It will be analyzed later.
17698 Vars.push_back(RefExpr);
17699 PrivateCopies.push_back(nullptr);
17700 }
17701 ValueDecl *D = Res.first;
17702 if (!D)
17703 continue;
17704
17705 QualType Type = D->getType();
17706 auto *VD = dyn_cast<VarDecl>(D);
17707
17708 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17709 // A variable that appears in a private clause must not have an incomplete
17710 // type or a reference type.
17711 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
17712 continue;
17713 Type = Type.getNonReferenceType();
17714
17715 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17716 // A variable that is privatized must not have a const-qualified type
17717 // unless it is of class type with a mutable member. This restriction does
17718 // not apply to the firstprivate clause.
17719 //
17720 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17721 // A variable that appears in a private clause must not have a
17722 // const-qualified type unless it is of class type with a mutable member.
17723 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
17724 continue;
17725
17726 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17727 // in a Construct]
17728 // Variables with the predetermined data-sharing attributes may not be
17729 // listed in data-sharing attributes clauses, except for the cases
17730 // listed below. For these exceptions only, listing a predetermined
17731 // variable in a data-sharing attribute clause is allowed and overrides
17732 // the variable's predetermined data-sharing attributes.
17733 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17734 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17735 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17736 << getOpenMPClauseName(OMPC_private);
17737 reportOriginalDsa(*this, DSAStack, D, DVar);
17738 continue;
17739 }
17740
17741 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17742 // Variably modified types are not supported for tasks.
17744 isOpenMPTaskingDirective(CurrDir)) {
17745 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17746 << getOpenMPClauseName(OMPC_private) << Type
17747 << getOpenMPDirectiveName(CurrDir);
17748 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
17750 Diag(D->getLocation(),
17751 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17752 << D;
17753 continue;
17754 }
17755
17756 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17757 // A list item cannot appear in both a map clause and a data-sharing
17758 // attribute clause on the same construct
17759 //
17760 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17761 // A list item cannot appear in both a map clause and a data-sharing
17762 // attribute clause on the same construct unless the construct is a
17763 // combined construct.
17764 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
17765 CurrDir == OMPD_target) {
17766 OpenMPClauseKind ConflictKind;
17767 if (DSAStack->checkMappableExprComponentListsForDecl(
17768 VD, /*CurrentRegionOnly=*/true,
17770 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17771 ConflictKind = WhereFoundClauseKind;
17772 return true;
17773 })) {
17774 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17775 << getOpenMPClauseName(OMPC_private)
17776 << getOpenMPClauseName(ConflictKind)
17777 << getOpenMPDirectiveName(CurrDir);
17778 reportOriginalDsa(*this, DSAStack, D, DVar);
17779 continue;
17780 }
17781 }
17782
17783 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17784 // A variable of class type (or array thereof) that appears in a private
17785 // clause requires an accessible, unambiguous default constructor for the
17786 // class type.
17787 // Generate helper private variable and initialize it with the default
17788 // value. The address of the original variable is replaced by the address of
17789 // the new private variable in CodeGen. This new variable is not added to
17790 // IdResolver, so the code in the OpenMP region uses original variable for
17791 // proper diagnostics.
17792 Type = Type.getUnqualifiedType();
17793 VarDecl *VDPrivate =
17794 buildVarDecl(*this, ELoc, Type, D->getName(),
17795 D->hasAttrs() ? &D->getAttrs() : nullptr,
17796 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17797 ActOnUninitializedDecl(VDPrivate);
17798 if (VDPrivate->isInvalidDecl())
17799 continue;
17800 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17801 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17802
17803 DeclRefExpr *Ref = nullptr;
17804 if (!VD && !CurContext->isDependentContext()) {
17805 auto *FD = dyn_cast<FieldDecl>(D);
17806 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17807 if (VD)
17808 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
17809 RefExpr->getExprLoc());
17810 else
17811 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
17812 }
17813 if (!IsImplicitClause)
17814 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17815 Vars.push_back((VD || CurContext->isDependentContext())
17816 ? RefExpr->IgnoreParens()
17817 : Ref);
17818 PrivateCopies.push_back(VDPrivateRefExpr);
17819 }
17820
17821 if (Vars.empty())
17822 return nullptr;
17823
17824 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
17825 PrivateCopies);
17826}
17827
17829 SourceLocation StartLoc,
17830 SourceLocation LParenLoc,
17831 SourceLocation EndLoc) {
17833 SmallVector<Expr *, 8> PrivateCopies;
17835 SmallVector<Decl *, 4> ExprCaptures;
17836 bool IsImplicitClause =
17837 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17838 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17839
17840 for (Expr *RefExpr : VarList) {
17841 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17842 SourceLocation ELoc;
17843 SourceRange ERange;
17844 Expr *SimpleRefExpr = RefExpr;
17845 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
17846 if (Res.second) {
17847 // It will be analyzed later.
17848 Vars.push_back(RefExpr);
17849 PrivateCopies.push_back(nullptr);
17850 Inits.push_back(nullptr);
17851 }
17852 ValueDecl *D = Res.first;
17853 if (!D)
17854 continue;
17855
17856 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17857 QualType Type = D->getType();
17858 auto *VD = dyn_cast<VarDecl>(D);
17859
17860 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17861 // A variable that appears in a private clause must not have an incomplete
17862 // type or a reference type.
17863 if (RequireCompleteType(ELoc, Type,
17864 diag::err_omp_firstprivate_incomplete_type))
17865 continue;
17866 Type = Type.getNonReferenceType();
17867
17868 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17869 // A variable of class type (or array thereof) that appears in a private
17870 // clause requires an accessible, unambiguous copy constructor for the
17871 // class type.
17873
17874 // If an implicit firstprivate variable found it was checked already.
17875 DSAStackTy::DSAVarData TopDVar;
17876 if (!IsImplicitClause) {
17877 DSAStackTy::DSAVarData DVar =
17878 DSAStack->getTopDSA(D, /*FromParent=*/false);
17879 TopDVar = DVar;
17880 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17881 bool IsConstant = ElemType.isConstant(Context);
17882 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17883 // A list item that specifies a given variable may not appear in more
17884 // than one clause on the same directive, except that a variable may be
17885 // specified in both firstprivate and lastprivate clauses.
17886 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17887 // A list item may appear in a firstprivate or lastprivate clause but not
17888 // both.
17889 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17890 (isOpenMPDistributeDirective(CurrDir) ||
17891 DVar.CKind != OMPC_lastprivate) &&
17892 DVar.RefExpr) {
17893 Diag(ELoc, diag::err_omp_wrong_dsa)
17894 << getOpenMPClauseName(DVar.CKind)
17895 << getOpenMPClauseName(OMPC_firstprivate);
17896 reportOriginalDsa(*this, DSAStack, D, DVar);
17897 continue;
17898 }
17899
17900 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17901 // in a Construct]
17902 // Variables with the predetermined data-sharing attributes may not be
17903 // listed in data-sharing attributes clauses, except for the cases
17904 // listed below. For these exceptions only, listing a predetermined
17905 // variable in a data-sharing attribute clause is allowed and overrides
17906 // the variable's predetermined data-sharing attributes.
17907 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17908 // in a Construct, C/C++, p.2]
17909 // Variables with const-qualified type having no mutable member may be
17910 // listed in a firstprivate clause, even if they are static data members.
17911 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17912 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17913 Diag(ELoc, diag::err_omp_wrong_dsa)
17914 << getOpenMPClauseName(DVar.CKind)
17915 << getOpenMPClauseName(OMPC_firstprivate);
17916 reportOriginalDsa(*this, DSAStack, D, DVar);
17917 continue;
17918 }
17919
17920 // OpenMP [2.9.3.4, Restrictions, p.2]
17921 // A list item that is private within a parallel region must not appear
17922 // in a firstprivate clause on a worksharing construct if any of the
17923 // worksharing regions arising from the worksharing construct ever bind
17924 // to any of the parallel regions arising from the parallel construct.
17925 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17926 // A list item that is private within a teams region must not appear in a
17927 // firstprivate clause on a distribute construct if any of the distribute
17928 // regions arising from the distribute construct ever bind to any of the
17929 // teams regions arising from the teams construct.
17930 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17931 // A list item that appears in a reduction clause of a teams construct
17932 // must not appear in a firstprivate clause on a distribute construct if
17933 // any of the distribute regions arising from the distribute construct
17934 // ever bind to any of the teams regions arising from the teams construct.
17935 if ((isOpenMPWorksharingDirective(CurrDir) ||
17936 isOpenMPDistributeDirective(CurrDir)) &&
17937 !isOpenMPParallelDirective(CurrDir) &&
17938 !isOpenMPTeamsDirective(CurrDir)) {
17939 DVar = DSAStack->getImplicitDSA(D, true);
17940 if (DVar.CKind != OMPC_shared &&
17941 (isOpenMPParallelDirective(DVar.DKind) ||
17942 isOpenMPTeamsDirective(DVar.DKind) ||
17943 DVar.DKind == OMPD_unknown)) {
17944 Diag(ELoc, diag::err_omp_required_access)
17945 << getOpenMPClauseName(OMPC_firstprivate)
17946 << getOpenMPClauseName(OMPC_shared);
17947 reportOriginalDsa(*this, DSAStack, D, DVar);
17948 continue;
17949 }
17950 }
17951 // OpenMP [2.9.3.4, Restrictions, p.3]
17952 // A list item that appears in a reduction clause of a parallel construct
17953 // must not appear in a firstprivate clause on a worksharing or task
17954 // construct if any of the worksharing or task regions arising from the
17955 // worksharing or task construct ever bind to any of the parallel regions
17956 // arising from the parallel construct.
17957 // OpenMP [2.9.3.4, Restrictions, p.4]
17958 // A list item that appears in a reduction clause in worksharing
17959 // construct must not appear in a firstprivate clause in a task construct
17960 // encountered during execution of any of the worksharing regions arising
17961 // from the worksharing construct.
17962 if (isOpenMPTaskingDirective(CurrDir)) {
17963 DVar = DSAStack->hasInnermostDSA(
17964 D,
17965 [](OpenMPClauseKind C, bool AppliedToPointee) {
17966 return C == OMPC_reduction && !AppliedToPointee;
17967 },
17968 [](OpenMPDirectiveKind K) {
17969 return isOpenMPParallelDirective(K) ||
17972 },
17973 /*FromParent=*/true);
17974 if (DVar.CKind == OMPC_reduction &&
17975 (isOpenMPParallelDirective(DVar.DKind) ||
17976 isOpenMPWorksharingDirective(DVar.DKind) ||
17977 isOpenMPTeamsDirective(DVar.DKind))) {
17978 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17979 << getOpenMPDirectiveName(DVar.DKind);
17980 reportOriginalDsa(*this, DSAStack, D, DVar);
17981 continue;
17982 }
17983 }
17984
17985 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17986 // A list item cannot appear in both a map clause and a data-sharing
17987 // attribute clause on the same construct
17988 //
17989 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17990 // A list item cannot appear in both a map clause and a data-sharing
17991 // attribute clause on the same construct unless the construct is a
17992 // combined construct.
17993 if ((LangOpts.OpenMP <= 45 &&
17995 CurrDir == OMPD_target) {
17996 OpenMPClauseKind ConflictKind;
17997 if (DSAStack->checkMappableExprComponentListsForDecl(
17998 VD, /*CurrentRegionOnly=*/true,
17999 [&ConflictKind](
18001 OpenMPClauseKind WhereFoundClauseKind) {
18002 ConflictKind = WhereFoundClauseKind;
18003 return true;
18004 })) {
18005 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18006 << getOpenMPClauseName(OMPC_firstprivate)
18007 << getOpenMPClauseName(ConflictKind)
18008 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18009 reportOriginalDsa(*this, DSAStack, D, DVar);
18010 continue;
18011 }
18012 }
18013 }
18014
18015 // Variably modified types are not supported for tasks.
18017 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18018 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18019 << getOpenMPClauseName(OMPC_firstprivate) << Type
18020 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18021 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18023 Diag(D->getLocation(),
18024 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18025 << D;
18026 continue;
18027 }
18028
18029 Type = Type.getUnqualifiedType();
18030 VarDecl *VDPrivate =
18031 buildVarDecl(*this, ELoc, Type, D->getName(),
18032 D->hasAttrs() ? &D->getAttrs() : nullptr,
18033 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18034 // Generate helper private variable and initialize it with the value of the
18035 // original variable. The address of the original variable is replaced by
18036 // the address of the new private variable in the CodeGen. This new variable
18037 // is not added to IdResolver, so the code in the OpenMP region uses
18038 // original variable for proper diagnostics and variable capturing.
18039 Expr *VDInitRefExpr = nullptr;
18040 // For arrays generate initializer for single element and replace it by the
18041 // original array element in CodeGen.
18042 if (Type->isArrayType()) {
18043 VarDecl *VDInit =
18044 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18045 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18046 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18047 ElemType = ElemType.getUnqualifiedType();
18048 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18049 ".firstprivate.temp");
18050 InitializedEntity Entity =
18053
18054 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18055 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18056 if (Result.isInvalid())
18057 VDPrivate->setInvalidDecl();
18058 else
18059 VDPrivate->setInit(Result.getAs<Expr>());
18060 // Remove temp variable declaration.
18061 Context.Deallocate(VDInitTemp);
18062 } else {
18063 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18064 ".firstprivate.temp");
18065 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18066 RefExpr->getExprLoc());
18067 AddInitializerToDecl(VDPrivate,
18068 DefaultLvalueConversion(VDInitRefExpr).get(),
18069 /*DirectInit=*/false);
18070 }
18071 if (VDPrivate->isInvalidDecl()) {
18072 if (IsImplicitClause) {
18073 Diag(RefExpr->getExprLoc(),
18074 diag::note_omp_task_predetermined_firstprivate_here);
18075 }
18076 continue;
18077 }
18078 CurContext->addDecl(VDPrivate);
18079 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18080 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18081 RefExpr->getExprLoc());
18082 DeclRefExpr *Ref = nullptr;
18083 if (!VD && !CurContext->isDependentContext()) {
18084 if (TopDVar.CKind == OMPC_lastprivate) {
18085 Ref = TopDVar.PrivateCopy;
18086 } else {
18087 auto *FD = dyn_cast<FieldDecl>(D);
18088 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18089 if (VD)
18090 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18091 RefExpr->getExprLoc());
18092 else
18093 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18094 if (VD || !isOpenMPCapturedDecl(D))
18095 ExprCaptures.push_back(Ref->getDecl());
18096 }
18097 }
18098 if (!IsImplicitClause)
18099 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18100 Vars.push_back((VD || CurContext->isDependentContext())
18101 ? RefExpr->IgnoreParens()
18102 : Ref);
18103 PrivateCopies.push_back(VDPrivateRefExpr);
18104 Inits.push_back(VDInitRefExpr);
18105 }
18106
18107 if (Vars.empty())
18108 return nullptr;
18109
18110 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18111 Vars, PrivateCopies, Inits,
18112 buildPreInits(Context, ExprCaptures));
18113}
18114
18117 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18118 SourceLocation LParenLoc, SourceLocation EndLoc) {
18119 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18120 assert(ColonLoc.isValid() && "Colon location must be valid.");
18121 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18122 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18123 /*Last=*/OMPC_LASTPRIVATE_unknown)
18124 << getOpenMPClauseName(OMPC_lastprivate);
18125 return nullptr;
18126 }
18127
18129 SmallVector<Expr *, 8> SrcExprs;
18130 SmallVector<Expr *, 8> DstExprs;
18131 SmallVector<Expr *, 8> AssignmentOps;
18132 SmallVector<Decl *, 4> ExprCaptures;
18133 SmallVector<Expr *, 4> ExprPostUpdates;
18134 for (Expr *RefExpr : VarList) {
18135 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18136 SourceLocation ELoc;
18137 SourceRange ERange;
18138 Expr *SimpleRefExpr = RefExpr;
18139 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18140 if (Res.second) {
18141 // It will be analyzed later.
18142 Vars.push_back(RefExpr);
18143 SrcExprs.push_back(nullptr);
18144 DstExprs.push_back(nullptr);
18145 AssignmentOps.push_back(nullptr);
18146 }
18147 ValueDecl *D = Res.first;
18148 if (!D)
18149 continue;
18150
18151 QualType Type = D->getType();
18152 auto *VD = dyn_cast<VarDecl>(D);
18153
18154 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18155 // A variable that appears in a lastprivate clause must not have an
18156 // incomplete type or a reference type.
18157 if (RequireCompleteType(ELoc, Type,
18158 diag::err_omp_lastprivate_incomplete_type))
18159 continue;
18160 Type = Type.getNonReferenceType();
18161
18162 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18163 // A variable that is privatized must not have a const-qualified type
18164 // unless it is of class type with a mutable member. This restriction does
18165 // not apply to the firstprivate clause.
18166 //
18167 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18168 // A variable that appears in a lastprivate clause must not have a
18169 // const-qualified type unless it is of class type with a mutable member.
18170 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18171 continue;
18172
18173 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18174 // A list item that appears in a lastprivate clause with the conditional
18175 // modifier must be a scalar variable.
18176 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18177 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18178 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18180 Diag(D->getLocation(),
18181 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18182 << D;
18183 continue;
18184 }
18185
18186 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18187 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18188 // in a Construct]
18189 // Variables with the predetermined data-sharing attributes may not be
18190 // listed in data-sharing attributes clauses, except for the cases
18191 // listed below.
18192 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18193 // A list item may appear in a firstprivate or lastprivate clause but not
18194 // both.
18195 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18196 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18197 (isOpenMPDistributeDirective(CurrDir) ||
18198 DVar.CKind != OMPC_firstprivate) &&
18199 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18200 Diag(ELoc, diag::err_omp_wrong_dsa)
18201 << getOpenMPClauseName(DVar.CKind)
18202 << getOpenMPClauseName(OMPC_lastprivate);
18203 reportOriginalDsa(*this, DSAStack, D, DVar);
18204 continue;
18205 }
18206
18207 // OpenMP [2.14.3.5, Restrictions, p.2]
18208 // A list item that is private within a parallel region, or that appears in
18209 // the reduction clause of a parallel construct, must not appear in a
18210 // lastprivate clause on a worksharing construct if any of the corresponding
18211 // worksharing regions ever binds to any of the corresponding parallel
18212 // regions.
18213 DSAStackTy::DSAVarData TopDVar = DVar;
18214 if (isOpenMPWorksharingDirective(CurrDir) &&
18215 !isOpenMPParallelDirective(CurrDir) &&
18216 !isOpenMPTeamsDirective(CurrDir)) {
18217 DVar = DSAStack->getImplicitDSA(D, true);
18218 if (DVar.CKind != OMPC_shared) {
18219 Diag(ELoc, diag::err_omp_required_access)
18220 << getOpenMPClauseName(OMPC_lastprivate)
18221 << getOpenMPClauseName(OMPC_shared);
18222 reportOriginalDsa(*this, DSAStack, D, DVar);
18223 continue;
18224 }
18225 }
18226
18227 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18228 // A variable of class type (or array thereof) that appears in a
18229 // lastprivate clause requires an accessible, unambiguous default
18230 // constructor for the class type, unless the list item is also specified
18231 // in a firstprivate clause.
18232 // A variable of class type (or array thereof) that appears in a
18233 // lastprivate clause requires an accessible, unambiguous copy assignment
18234 // operator for the class type.
18236 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18237 Type.getUnqualifiedType(), ".lastprivate.src",
18238 D->hasAttrs() ? &D->getAttrs() : nullptr);
18239 DeclRefExpr *PseudoSrcExpr =
18240 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18241 VarDecl *DstVD =
18242 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18243 D->hasAttrs() ? &D->getAttrs() : nullptr);
18244 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18245 // For arrays generate assignment operation for single element and replace
18246 // it by the original array element in CodeGen.
18247 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18248 PseudoDstExpr, PseudoSrcExpr);
18249 if (AssignmentOp.isInvalid())
18250 continue;
18251 AssignmentOp =
18252 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18253 if (AssignmentOp.isInvalid())
18254 continue;
18255
18256 DeclRefExpr *Ref = nullptr;
18257 if (!VD && !CurContext->isDependentContext()) {
18258 if (TopDVar.CKind == OMPC_firstprivate) {
18259 Ref = TopDVar.PrivateCopy;
18260 } else {
18261 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18262 if (!isOpenMPCapturedDecl(D))
18263 ExprCaptures.push_back(Ref->getDecl());
18264 }
18265 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18266 (!isOpenMPCapturedDecl(D) &&
18267 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18268 ExprResult RefRes = DefaultLvalueConversion(Ref);
18269 if (!RefRes.isUsable())
18270 continue;
18271 ExprResult PostUpdateRes =
18272 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18273 RefRes.get());
18274 if (!PostUpdateRes.isUsable())
18275 continue;
18276 ExprPostUpdates.push_back(
18277 IgnoredValueConversions(PostUpdateRes.get()).get());
18278 }
18279 }
18280 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18281 Vars.push_back((VD || CurContext->isDependentContext())
18282 ? RefExpr->IgnoreParens()
18283 : Ref);
18284 SrcExprs.push_back(PseudoSrcExpr);
18285 DstExprs.push_back(PseudoDstExpr);
18286 AssignmentOps.push_back(AssignmentOp.get());
18287 }
18288
18289 if (Vars.empty())
18290 return nullptr;
18291
18292 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18293 Vars, SrcExprs, DstExprs, AssignmentOps,
18294 LPKind, LPKindLoc, ColonLoc,
18295 buildPreInits(Context, ExprCaptures),
18296 buildPostUpdate(*this, ExprPostUpdates));
18297}
18298
18300 SourceLocation StartLoc,
18301 SourceLocation LParenLoc,
18302 SourceLocation EndLoc) {
18304 for (Expr *RefExpr : VarList) {
18305 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18306 SourceLocation ELoc;
18307 SourceRange ERange;
18308 Expr *SimpleRefExpr = RefExpr;
18309 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18310 if (Res.second) {
18311 // It will be analyzed later.
18312 Vars.push_back(RefExpr);
18313 }
18314 ValueDecl *D = Res.first;
18315 if (!D)
18316 continue;
18317
18318 auto *VD = dyn_cast<VarDecl>(D);
18319 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18320 // in a Construct]
18321 // Variables with the predetermined data-sharing attributes may not be
18322 // listed in data-sharing attributes clauses, except for the cases
18323 // listed below. For these exceptions only, listing a predetermined
18324 // variable in a data-sharing attribute clause is allowed and overrides
18325 // the variable's predetermined data-sharing attributes.
18326 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18327 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18328 DVar.RefExpr) {
18329 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18330 << getOpenMPClauseName(OMPC_shared);
18331 reportOriginalDsa(*this, DSAStack, D, DVar);
18332 continue;
18333 }
18334
18335 DeclRefExpr *Ref = nullptr;
18337 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18338 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18339 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18340 ? RefExpr->IgnoreParens()
18341 : Ref);
18342 }
18343
18344 if (Vars.empty())
18345 return nullptr;
18346
18347 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
18348}
18349
18350namespace {
18351class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18352 DSAStackTy *Stack;
18353
18354public:
18355 bool VisitDeclRefExpr(DeclRefExpr *E) {
18356 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18357 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18358 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18359 return false;
18360 if (DVar.CKind != OMPC_unknown)
18361 return true;
18362 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18363 VD,
18364 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18365 return isOpenMPPrivate(C) && !AppliedToPointee;
18366 },
18367 [](OpenMPDirectiveKind) { return true; },
18368 /*FromParent=*/true);
18369 return DVarPrivate.CKind != OMPC_unknown;
18370 }
18371 return false;
18372 }
18373 bool VisitStmt(Stmt *S) {
18374 for (Stmt *Child : S->children()) {
18375 if (Child && Visit(Child))
18376 return true;
18377 }
18378 return false;
18379 }
18380 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18381};
18382} // namespace
18383
18384namespace {
18385// Transform MemberExpression for specified FieldDecl of current class to
18386// DeclRefExpr to specified OMPCapturedExprDecl.
18387class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18388 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18389 ValueDecl *Field = nullptr;
18390 DeclRefExpr *CapturedExpr = nullptr;
18391
18392public:
18393 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18394 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18395
18396 ExprResult TransformMemberExpr(MemberExpr *E) {
18397 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18398 E->getMemberDecl() == Field) {
18399 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18400 return CapturedExpr;
18401 }
18402 return BaseTransform::TransformMemberExpr(E);
18403 }
18404 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18405};
18406} // namespace
18407
18408template <typename T, typename U>
18410 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18411 for (U &Set : Lookups) {
18412 for (auto *D : Set) {
18413 if (T Res = Gen(cast<ValueDecl>(D)))
18414 return Res;
18415 }
18416 }
18417 return T();
18418}
18419
18421 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18422
18423 for (auto RD : D->redecls()) {
18424 // Don't bother with extra checks if we already know this one isn't visible.
18425 if (RD == D)
18426 continue;
18427
18428 auto ND = cast<NamedDecl>(RD);
18429 if (LookupResult::isVisible(SemaRef, ND))
18430 return ND;
18431 }
18432
18433 return nullptr;
18434}
18435
18436static void
18438 SourceLocation Loc, QualType Ty,
18440 // Find all of the associated namespaces and classes based on the
18441 // arguments we have.
18442 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18443 Sema::AssociatedClassSet AssociatedClasses;
18444 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18445 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18446 AssociatedClasses);
18447
18448 // C++ [basic.lookup.argdep]p3:
18449 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18450 // and let Y be the lookup set produced by argument dependent
18451 // lookup (defined as follows). If X contains [...] then Y is
18452 // empty. Otherwise Y is the set of declarations found in the
18453 // namespaces associated with the argument types as described
18454 // below. The set of declarations found by the lookup of the name
18455 // is the union of X and Y.
18456 //
18457 // Here, we compute Y and add its members to the overloaded
18458 // candidate set.
18459 for (auto *NS : AssociatedNamespaces) {
18460 // When considering an associated namespace, the lookup is the
18461 // same as the lookup performed when the associated namespace is
18462 // used as a qualifier (3.4.3.2) except that:
18463 //
18464 // -- Any using-directives in the associated namespace are
18465 // ignored.
18466 //
18467 // -- Any namespace-scope friend functions declared in
18468 // associated classes are visible within their respective
18469 // namespaces even if they are not visible during an ordinary
18470 // lookup (11.4).
18471 DeclContext::lookup_result R = NS->lookup(Id.getName());
18472 for (auto *D : R) {
18473 auto *Underlying = D;
18474 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18475 Underlying = USD->getTargetDecl();
18476
18477 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18478 !isa<OMPDeclareMapperDecl>(Underlying))
18479 continue;
18480
18481 if (!SemaRef.isVisible(D)) {
18482 D = findAcceptableDecl(SemaRef, D);
18483 if (!D)
18484 continue;
18485 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18486 Underlying = USD->getTargetDecl();
18487 }
18488 Lookups.emplace_back();
18489 Lookups.back().addDecl(Underlying);
18490 }
18491 }
18492}
18493
18494static ExprResult
18496 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18497 const DeclarationNameInfo &ReductionId, QualType Ty,
18498 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18499 if (ReductionIdScopeSpec.isInvalid())
18500 return ExprError();
18501 SmallVector<UnresolvedSet<8>, 4> Lookups;
18502 if (S) {
18503 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18504 Lookup.suppressDiagnostics();
18505 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
18506 NamedDecl *D = Lookup.getRepresentativeDecl();
18507 do {
18508 S = S->getParent();
18509 } while (S && !S->isDeclScope(D));
18510 if (S)
18511 S = S->getParent();
18512 Lookups.emplace_back();
18513 Lookups.back().append(Lookup.begin(), Lookup.end());
18514 Lookup.clear();
18515 }
18516 } else if (auto *ULE =
18517 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18518 Lookups.push_back(UnresolvedSet<8>());
18519 Decl *PrevD = nullptr;
18520 for (NamedDecl *D : ULE->decls()) {
18521 if (D == PrevD)
18522 Lookups.push_back(UnresolvedSet<8>());
18523 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18524 Lookups.back().addDecl(DRD);
18525 PrevD = D;
18526 }
18527 }
18528 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18532 return !D->isInvalidDecl() &&
18533 (D->getType()->isDependentType() ||
18534 D->getType()->isInstantiationDependentType() ||
18535 D->getType()->containsUnexpandedParameterPack());
18536 })) {
18537 UnresolvedSet<8> ResSet;
18538 for (const UnresolvedSet<8> &Set : Lookups) {
18539 if (Set.empty())
18540 continue;
18541 ResSet.append(Set.begin(), Set.end());
18542 // The last item marks the end of all declarations at the specified scope.
18543 ResSet.addDecl(Set[Set.size() - 1]);
18544 }
18546 SemaRef.Context, /*NamingClass=*/nullptr,
18547 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18548 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
18549 }
18550 // Lookup inside the classes.
18551 // C++ [over.match.oper]p3:
18552 // For a unary operator @ with an operand of a type whose
18553 // cv-unqualified version is T1, and for a binary operator @ with
18554 // a left operand of a type whose cv-unqualified version is T1 and
18555 // a right operand of a type whose cv-unqualified version is T2,
18556 // three sets of candidate functions, designated member
18557 // candidates, non-member candidates and built-in candidates, are
18558 // constructed as follows:
18559 // -- If T1 is a complete class type or a class currently being
18560 // defined, the set of member candidates is the result of the
18561 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18562 // the set of member candidates is empty.
18563 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18564 Lookup.suppressDiagnostics();
18565 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18566 // Complete the type if it can be completed.
18567 // If the type is neither complete nor being defined, bail out now.
18568 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18569 TyRec->getDecl()->getDefinition()) {
18570 Lookup.clear();
18571 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18572 if (Lookup.empty()) {
18573 Lookups.emplace_back();
18574 Lookups.back().append(Lookup.begin(), Lookup.end());
18575 }
18576 }
18577 }
18578 // Perform ADL.
18579 if (SemaRef.getLangOpts().CPlusPlus)
18580 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18582 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18583 if (!D->isInvalidDecl() &&
18584 SemaRef.Context.hasSameType(D->getType(), Ty))
18585 return D;
18586 return nullptr;
18587 }))
18588 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18589 VK_LValue, Loc);
18590 if (SemaRef.getLangOpts().CPlusPlus) {
18592 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18593 if (!D->isInvalidDecl() &&
18594 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18595 !Ty.isMoreQualifiedThan(D->getType()))
18596 return D;
18597 return nullptr;
18598 })) {
18599 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18600 /*DetectVirtual=*/false);
18601 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18602 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18603 VD->getType().getUnqualifiedType()))) {
18604 if (SemaRef.CheckBaseClassAccess(
18605 Loc, VD->getType(), Ty, Paths.front(),
18606 /*DiagID=*/0) != Sema::AR_inaccessible) {
18607 SemaRef.BuildBasePathArray(Paths, BasePath);
18608 return SemaRef.BuildDeclRefExpr(
18609 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
18610 }
18611 }
18612 }
18613 }
18614 }
18615 if (ReductionIdScopeSpec.isSet()) {
18616 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18617 << Ty << Range;
18618 return ExprError();
18619 }
18620 return ExprEmpty();
18621}
18622
18623namespace {
18624/// Data for the reduction-based clauses.
18625struct ReductionData {
18626 /// List of original reduction items.
18628 /// List of private copies of the reduction items.
18629 SmallVector<Expr *, 8> Privates;
18630 /// LHS expressions for the reduction_op expressions.
18632 /// RHS expressions for the reduction_op expressions.
18634 /// Reduction operation expression.
18635 SmallVector<Expr *, 8> ReductionOps;
18636 /// inscan copy operation expressions.
18637 SmallVector<Expr *, 8> InscanCopyOps;
18638 /// inscan copy temp array expressions for prefix sums.
18639 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18640 /// inscan copy temp array element expressions for prefix sums.
18641 SmallVector<Expr *, 8> InscanCopyArrayElems;
18642 /// Taskgroup descriptors for the corresponding reduction items in
18643 /// in_reduction clauses.
18644 SmallVector<Expr *, 8> TaskgroupDescriptors;
18645 /// List of captures for clause.
18646 SmallVector<Decl *, 4> ExprCaptures;
18647 /// List of postupdate expressions.
18648 SmallVector<Expr *, 4> ExprPostUpdates;
18649 /// Reduction modifier.
18650 unsigned RedModifier = 0;
18651 ReductionData() = delete;
18652 /// Reserves required memory for the reduction data.
18653 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18654 Vars.reserve(Size);
18655 Privates.reserve(Size);
18656 LHSs.reserve(Size);
18657 RHSs.reserve(Size);
18658 ReductionOps.reserve(Size);
18659 if (RedModifier == OMPC_REDUCTION_inscan) {
18660 InscanCopyOps.reserve(Size);
18661 InscanCopyArrayTemps.reserve(Size);
18662 InscanCopyArrayElems.reserve(Size);
18663 }
18664 TaskgroupDescriptors.reserve(Size);
18665 ExprCaptures.reserve(Size);
18666 ExprPostUpdates.reserve(Size);
18667 }
18668 /// Stores reduction item and reduction operation only (required for dependent
18669 /// reduction item).
18670 void push(Expr *Item, Expr *ReductionOp) {
18671 Vars.emplace_back(Item);
18672 Privates.emplace_back(nullptr);
18673 LHSs.emplace_back(nullptr);
18674 RHSs.emplace_back(nullptr);
18675 ReductionOps.emplace_back(ReductionOp);
18676 TaskgroupDescriptors.emplace_back(nullptr);
18677 if (RedModifier == OMPC_REDUCTION_inscan) {
18678 InscanCopyOps.push_back(nullptr);
18679 InscanCopyArrayTemps.push_back(nullptr);
18680 InscanCopyArrayElems.push_back(nullptr);
18681 }
18682 }
18683 /// Stores reduction data.
18684 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18685 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18686 Expr *CopyArrayElem) {
18687 Vars.emplace_back(Item);
18688 Privates.emplace_back(Private);
18689 LHSs.emplace_back(LHS);
18690 RHSs.emplace_back(RHS);
18691 ReductionOps.emplace_back(ReductionOp);
18692 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18693 if (RedModifier == OMPC_REDUCTION_inscan) {
18694 InscanCopyOps.push_back(CopyOp);
18695 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18696 InscanCopyArrayElems.push_back(CopyArrayElem);
18697 } else {
18698 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18699 CopyArrayElem == nullptr &&
18700 "Copy operation must be used for inscan reductions only.");
18701 }
18702 }
18703};
18704} // namespace
18705
18707 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
18708 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18709 const Expr *Length = OASE->getLength();
18710 if (Length == nullptr) {
18711 // For array sections of the form [1:] or [:], we would need to analyze
18712 // the lower bound...
18713 if (OASE->getColonLocFirst().isValid())
18714 return false;
18715
18716 // This is an array subscript which has implicit length 1!
18717 SingleElement = true;
18718 ArraySizes.push_back(llvm::APSInt::get(1));
18719 } else {
18721 if (!Length->EvaluateAsInt(Result, Context))
18722 return false;
18723
18724 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18725 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18726 ArraySizes.push_back(ConstantLengthValue);
18727 }
18728
18729 // Get the base of this array section and walk up from there.
18730 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18731
18732 // We require length = 1 for all array sections except the right-most to
18733 // guarantee that the memory region is contiguous and has no holes in it.
18734 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
18735 Length = TempOASE->getLength();
18736 if (Length == nullptr) {
18737 // For array sections of the form [1:] or [:], we would need to analyze
18738 // the lower bound...
18739 if (OASE->getColonLocFirst().isValid())
18740 return false;
18741
18742 // This is an array subscript which has implicit length 1!
18743 ArraySizes.push_back(llvm::APSInt::get(1));
18744 } else {
18746 if (!Length->EvaluateAsInt(Result, Context))
18747 return false;
18748
18749 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18750 if (ConstantLengthValue.getSExtValue() != 1)
18751 return false;
18752
18753 ArraySizes.push_back(ConstantLengthValue);
18754 }
18755 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18756 }
18757
18758 // If we have a single element, we don't need to add the implicit lengths.
18759 if (!SingleElement) {
18760 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18761 // Has implicit length 1!
18762 ArraySizes.push_back(llvm::APSInt::get(1));
18763 Base = TempASE->getBase()->IgnoreParenImpCasts();
18764 }
18765 }
18766
18767 // This array section can be privatized as a single value or as a constant
18768 // sized array.
18769 return true;
18770}
18771
18772static BinaryOperatorKind
18774 if (BOK == BO_Add)
18775 return BO_AddAssign;
18776 if (BOK == BO_Mul)
18777 return BO_MulAssign;
18778 if (BOK == BO_And)
18779 return BO_AndAssign;
18780 if (BOK == BO_Or)
18781 return BO_OrAssign;
18782 if (BOK == BO_Xor)
18783 return BO_XorAssign;
18784 return BOK;
18785}
18786
18788 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18789 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18790 SourceLocation ColonLoc, SourceLocation EndLoc,
18791 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18792 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18793 DeclarationName DN = ReductionId.getName();
18795 BinaryOperatorKind BOK = BO_Comma;
18796
18797 ASTContext &Context = S.Context;
18798 // OpenMP [2.14.3.6, reduction clause]
18799 // C
18800 // reduction-identifier is either an identifier or one of the following
18801 // operators: +, -, *, &, |, ^, && and ||
18802 // C++
18803 // reduction-identifier is either an id-expression or one of the following
18804 // operators: +, -, *, &, |, ^, && and ||
18805 switch (OOK) {
18806 case OO_Plus:
18807 case OO_Minus:
18808 BOK = BO_Add;
18809 break;
18810 case OO_Star:
18811 BOK = BO_Mul;
18812 break;
18813 case OO_Amp:
18814 BOK = BO_And;
18815 break;
18816 case OO_Pipe:
18817 BOK = BO_Or;
18818 break;
18819 case OO_Caret:
18820 BOK = BO_Xor;
18821 break;
18822 case OO_AmpAmp:
18823 BOK = BO_LAnd;
18824 break;
18825 case OO_PipePipe:
18826 BOK = BO_LOr;
18827 break;
18828 case OO_New:
18829 case OO_Delete:
18830 case OO_Array_New:
18831 case OO_Array_Delete:
18832 case OO_Slash:
18833 case OO_Percent:
18834 case OO_Tilde:
18835 case OO_Exclaim:
18836 case OO_Equal:
18837 case OO_Less:
18838 case OO_Greater:
18839 case OO_LessEqual:
18840 case OO_GreaterEqual:
18841 case OO_PlusEqual:
18842 case OO_MinusEqual:
18843 case OO_StarEqual:
18844 case OO_SlashEqual:
18845 case OO_PercentEqual:
18846 case OO_CaretEqual:
18847 case OO_AmpEqual:
18848 case OO_PipeEqual:
18849 case OO_LessLess:
18850 case OO_GreaterGreater:
18851 case OO_LessLessEqual:
18852 case OO_GreaterGreaterEqual:
18853 case OO_EqualEqual:
18854 case OO_ExclaimEqual:
18855 case OO_Spaceship:
18856 case OO_PlusPlus:
18857 case OO_MinusMinus:
18858 case OO_Comma:
18859 case OO_ArrowStar:
18860 case OO_Arrow:
18861 case OO_Call:
18862 case OO_Subscript:
18863 case OO_Conditional:
18864 case OO_Coawait:
18866 llvm_unreachable("Unexpected reduction identifier");
18867 case OO_None:
18868 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18869 if (II->isStr("max"))
18870 BOK = BO_GT;
18871 else if (II->isStr("min"))
18872 BOK = BO_LT;
18873 }
18874 break;
18875 }
18876 SourceRange ReductionIdRange;
18877 if (ReductionIdScopeSpec.isValid())
18878 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18879 else
18880 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18881 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18882
18883 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18884 bool FirstIter = true;
18885 for (Expr *RefExpr : VarList) {
18886 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18887 // OpenMP [2.1, C/C++]
18888 // A list item is a variable or array section, subject to the restrictions
18889 // specified in Section 2.4 on page 42 and in each of the sections
18890 // describing clauses and directives for which a list appears.
18891 // OpenMP [2.14.3.3, Restrictions, p.1]
18892 // A variable that is part of another variable (as an array or
18893 // structure element) cannot appear in a private clause.
18894 if (!FirstIter && IR != ER)
18895 ++IR;
18896 FirstIter = false;
18897 SourceLocation ELoc;
18898 SourceRange ERange;
18899 Expr *SimpleRefExpr = RefExpr;
18900 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18901 /*AllowArraySection=*/true);
18902 if (Res.second) {
18903 // Try to find 'declare reduction' corresponding construct before using
18904 // builtin/overloaded operators.
18905 QualType Type = Context.DependentTy;
18906 CXXCastPath BasePath;
18907 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18908 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18909 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18910 Expr *ReductionOp = nullptr;
18911 if (S.CurContext->isDependentContext() &&
18912 (DeclareReductionRef.isUnset() ||
18913 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18914 ReductionOp = DeclareReductionRef.get();
18915 // It will be analyzed later.
18916 RD.push(RefExpr, ReductionOp);
18917 }
18918 ValueDecl *D = Res.first;
18919 if (!D)
18920 continue;
18921
18922 Expr *TaskgroupDescriptor = nullptr;
18923 QualType Type;
18924 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18925 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
18926 if (ASE) {
18927 Type = ASE->getType().getNonReferenceType();
18928 } else if (OASE) {
18929 QualType BaseType =
18931 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18932 Type = ATy->getElementType();
18933 else
18934 Type = BaseType->getPointeeType();
18935 Type = Type.getNonReferenceType();
18936 } else {
18938 }
18939 auto *VD = dyn_cast<VarDecl>(D);
18940
18941 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18942 // A variable that appears in a private clause must not have an incomplete
18943 // type or a reference type.
18944 if (S.RequireCompleteType(ELoc, D->getType(),
18945 diag::err_omp_reduction_incomplete_type))
18946 continue;
18947 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18948 // A list item that appears in a reduction clause must not be
18949 // const-qualified.
18950 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18951 /*AcceptIfMutable*/ false, ASE || OASE))
18952 continue;
18953
18954 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18955 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18956 // If a list-item is a reference type then it must bind to the same object
18957 // for all threads of the team.
18958 if (!ASE && !OASE) {
18959 if (VD) {
18960 VarDecl *VDDef = VD->getDefinition();
18961 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18962 DSARefChecker Check(Stack);
18963 if (Check.Visit(VDDef->getInit())) {
18964 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18965 << getOpenMPClauseName(ClauseKind) << ERange;
18966 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18967 continue;
18968 }
18969 }
18970 }
18971
18972 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18973 // in a Construct]
18974 // Variables with the predetermined data-sharing attributes may not be
18975 // listed in data-sharing attributes clauses, except for the cases
18976 // listed below. For these exceptions only, listing a predetermined
18977 // variable in a data-sharing attribute clause is allowed and overrides
18978 // the variable's predetermined data-sharing attributes.
18979 // OpenMP [2.14.3.6, Restrictions, p.3]
18980 // Any number of reduction clauses can be specified on the directive,
18981 // but a list item can appear only once in the reduction clauses for that
18982 // directive.
18983 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18984 if (DVar.CKind == OMPC_reduction) {
18985 S.Diag(ELoc, diag::err_omp_once_referenced)
18986 << getOpenMPClauseName(ClauseKind);
18987 if (DVar.RefExpr)
18988 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18989 continue;
18990 }
18991 if (DVar.CKind != OMPC_unknown) {
18992 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18993 << getOpenMPClauseName(DVar.CKind)
18994 << getOpenMPClauseName(OMPC_reduction);
18995 reportOriginalDsa(S, Stack, D, DVar);
18996 continue;
18997 }
18998
18999 // OpenMP [2.14.3.6, Restrictions, p.1]
19000 // A list item that appears in a reduction clause of a worksharing
19001 // construct must be shared in the parallel regions to which any of the
19002 // worksharing regions arising from the worksharing construct bind.
19003 if (isOpenMPWorksharingDirective(CurrDir) &&
19004 !isOpenMPParallelDirective(CurrDir) &&
19005 !isOpenMPTeamsDirective(CurrDir)) {
19006 DVar = Stack->getImplicitDSA(D, true);
19007 if (DVar.CKind != OMPC_shared) {
19008 S.Diag(ELoc, diag::err_omp_required_access)
19009 << getOpenMPClauseName(OMPC_reduction)
19010 << getOpenMPClauseName(OMPC_shared);
19011 reportOriginalDsa(S, Stack, D, DVar);
19012 continue;
19013 }
19014 }
19015 } else {
19016 // Threadprivates cannot be shared between threads, so dignose if the base
19017 // is a threadprivate variable.
19018 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19019 if (DVar.CKind == OMPC_threadprivate) {
19020 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19021 << getOpenMPClauseName(DVar.CKind)
19022 << getOpenMPClauseName(OMPC_reduction);
19023 reportOriginalDsa(S, Stack, D, DVar);
19024 continue;
19025 }
19026 }
19027
19028 // Try to find 'declare reduction' corresponding construct before using
19029 // builtin/overloaded operators.
19030 CXXCastPath BasePath;
19031 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19032 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19033 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19034 if (DeclareReductionRef.isInvalid())
19035 continue;
19036 if (S.CurContext->isDependentContext() &&
19037 (DeclareReductionRef.isUnset() ||
19038 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19039 RD.push(RefExpr, DeclareReductionRef.get());
19040 continue;
19041 }
19042 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19043 // Not allowed reduction identifier is found.
19044 S.Diag(ReductionId.getBeginLoc(),
19045 diag::err_omp_unknown_reduction_identifier)
19046 << Type << ReductionIdRange;
19047 continue;
19048 }
19049
19050 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19051 // The type of a list item that appears in a reduction clause must be valid
19052 // for the reduction-identifier. For a max or min reduction in C, the type
19053 // of the list item must be an allowed arithmetic data type: char, int,
19054 // float, double, or _Bool, possibly modified with long, short, signed, or
19055 // unsigned. For a max or min reduction in C++, the type of the list item
19056 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19057 // double, or bool, possibly modified with long, short, signed, or unsigned.
19058 if (DeclareReductionRef.isUnset()) {
19059 if ((BOK == BO_GT || BOK == BO_LT) &&
19060 !(Type->isScalarType() ||
19061 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19062 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19063 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19064 if (!ASE && !OASE) {
19065 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19067 S.Diag(D->getLocation(),
19068 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19069 << D;
19070 }
19071 continue;
19072 }
19073 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19074 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19075 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19076 << getOpenMPClauseName(ClauseKind);
19077 if (!ASE && !OASE) {
19078 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19080 S.Diag(D->getLocation(),
19081 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19082 << D;
19083 }
19084 continue;
19085 }
19086 }
19087
19088 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19089 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19090 D->hasAttrs() ? &D->getAttrs() : nullptr);
19091 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19092 D->hasAttrs() ? &D->getAttrs() : nullptr);
19093 QualType PrivateTy = Type;
19094
19095 // Try if we can determine constant lengths for all array sections and avoid
19096 // the VLA.
19097 bool ConstantLengthOASE = false;
19098 if (OASE) {
19099 bool SingleElement;
19101 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19102 Context, OASE, SingleElement, ArraySizes);
19103
19104 // If we don't have a single element, we must emit a constant array type.
19105 if (ConstantLengthOASE && !SingleElement) {
19106 for (llvm::APSInt &Size : ArraySizes)
19107 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19109 /*IndexTypeQuals=*/0);
19110 }
19111 }
19112
19113 if ((OASE && !ConstantLengthOASE) ||
19114 (!OASE && !ASE &&
19116 if (!Context.getTargetInfo().isVLASupported()) {
19117 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19118 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19119 S.Diag(ELoc, diag::note_vla_unsupported);
19120 continue;
19121 } else {
19122 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19123 S.targetDiag(ELoc, diag::note_vla_unsupported);
19124 }
19125 }
19126 // For arrays/array sections only:
19127 // Create pseudo array type for private copy. The size for this array will
19128 // be generated during codegen.
19129 // For array subscripts or single variables Private Ty is the same as Type
19130 // (type of the variable or single array element).
19131 PrivateTy = Context.getVariableArrayType(
19132 Type,
19133 new (Context)
19134 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19135 ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
19136 } else if (!ASE && !OASE &&
19137 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19138 PrivateTy = D->getType().getNonReferenceType();
19139 }
19140 // Private copy.
19141 VarDecl *PrivateVD =
19142 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19143 D->hasAttrs() ? &D->getAttrs() : nullptr,
19144 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19145 // Add initializer for private variable.
19146 Expr *Init = nullptr;
19147 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19148 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19149 if (DeclareReductionRef.isUsable()) {
19150 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19151 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19152 if (DRD->getInitializer()) {
19153 Init = DRDRef;
19154 RHSVD->setInit(DRDRef);
19156 }
19157 } else {
19158 switch (BOK) {
19159 case BO_Add:
19160 case BO_Xor:
19161 case BO_Or:
19162 case BO_LOr:
19163 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19165 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19166 break;
19167 case BO_Mul:
19168 case BO_LAnd:
19169 if (Type->isScalarType() || Type->isAnyComplexType()) {
19170 // '*' and '&&' reduction ops - initializer is '1'.
19171 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19172 }
19173 break;
19174 case BO_And: {
19175 // '&' reduction op - initializer is '~0'.
19176 QualType OrigType = Type;
19177 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19178 Type = ComplexTy->getElementType();
19179 if (Type->isRealFloatingType()) {
19180 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19181 Context.getFloatTypeSemantics(Type));
19182 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19183 Type, ELoc);
19184 } else if (Type->isScalarType()) {
19185 uint64_t Size = Context.getTypeSize(Type);
19186 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19187 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19188 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19189 }
19190 if (Init && OrigType->isAnyComplexType()) {
19191 // Init = 0xFFFF + 0xFFFFi;
19192 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19193 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19194 }
19195 Type = OrigType;
19196 break;
19197 }
19198 case BO_LT:
19199 case BO_GT: {
19200 // 'min' reduction op - initializer is 'Largest representable number in
19201 // the reduction list item type'.
19202 // 'max' reduction op - initializer is 'Least representable number in
19203 // the reduction list item type'.
19204 if (Type->isIntegerType() || Type->isPointerType()) {
19205 bool IsSigned = Type->hasSignedIntegerRepresentation();
19206 uint64_t Size = Context.getTypeSize(Type);
19207 QualType IntTy =
19208 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19209 llvm::APInt InitValue =
19210 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19211 : llvm::APInt::getMinValue(Size)
19212 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19213 : llvm::APInt::getMaxValue(Size);
19214 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19215 if (Type->isPointerType()) {
19216 // Cast to pointer type.
19218 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19219 if (CastExpr.isInvalid())
19220 continue;
19221 Init = CastExpr.get();
19222 }
19223 } else if (Type->isRealFloatingType()) {
19224 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19225 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19226 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19227 Type, ELoc);
19228 }
19229 break;
19230 }
19231 case BO_PtrMemD:
19232 case BO_PtrMemI:
19233 case BO_MulAssign:
19234 case BO_Div:
19235 case BO_Rem:
19236 case BO_Sub:
19237 case BO_Shl:
19238 case BO_Shr:
19239 case BO_LE:
19240 case BO_GE:
19241 case BO_EQ:
19242 case BO_NE:
19243 case BO_Cmp:
19244 case BO_AndAssign:
19245 case BO_XorAssign:
19246 case BO_OrAssign:
19247 case BO_Assign:
19248 case BO_AddAssign:
19249 case BO_SubAssign:
19250 case BO_DivAssign:
19251 case BO_RemAssign:
19252 case BO_ShlAssign:
19253 case BO_ShrAssign:
19254 case BO_Comma:
19255 llvm_unreachable("Unexpected reduction operation");
19256 }
19257 }
19258 if (Init && DeclareReductionRef.isUnset()) {
19259 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19260 // Store initializer for single element in private copy. Will be used
19261 // during codegen.
19262 PrivateVD->setInit(RHSVD->getInit());
19263 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19264 } else if (!Init) {
19265 S.ActOnUninitializedDecl(RHSVD);
19266 // Store initializer for single element in private copy. Will be used
19267 // during codegen.
19268 PrivateVD->setInit(RHSVD->getInit());
19269 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19270 }
19271 if (RHSVD->isInvalidDecl())
19272 continue;
19273 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19274 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19275 << Type << ReductionIdRange;
19276 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19278 S.Diag(D->getLocation(),
19279 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19280 << D;
19281 continue;
19282 }
19283 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19284 ExprResult ReductionOp;
19285 if (DeclareReductionRef.isUsable()) {
19286 QualType RedTy = DeclareReductionRef.get()->getType();
19287 QualType PtrRedTy = Context.getPointerType(RedTy);
19288 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19289 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19290 if (!BasePath.empty()) {
19291 LHS = S.DefaultLvalueConversion(LHS.get());
19292 RHS = S.DefaultLvalueConversion(RHS.get());
19294 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19295 LHS.get()->getValueKind(), FPOptionsOverride());
19297 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19298 RHS.get()->getValueKind(), FPOptionsOverride());
19299 }
19301 QualType Params[] = {PtrRedTy, PtrRedTy};
19302 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19303 auto *OVE = new (Context) OpaqueValueExpr(
19304 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19305 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19306 Expr *Args[] = {LHS.get(), RHS.get()};
19307 ReductionOp =
19308 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19310 } else {
19312 if (Type->isRecordType() && CombBOK != BOK) {
19314 ReductionOp =
19315 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19316 CombBOK, LHSDRE, RHSDRE);
19317 }
19318 if (!ReductionOp.isUsable()) {
19319 ReductionOp =
19320 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19321 LHSDRE, RHSDRE);
19322 if (ReductionOp.isUsable()) {
19323 if (BOK != BO_LT && BOK != BO_GT) {
19324 ReductionOp =
19325 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19326 BO_Assign, LHSDRE, ReductionOp.get());
19327 } else {
19328 auto *ConditionalOp = new (Context)
19329 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19330 RHSDRE, Type, VK_LValue, OK_Ordinary);
19331 ReductionOp =
19332 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19333 BO_Assign, LHSDRE, ConditionalOp);
19334 }
19335 }
19336 }
19337 if (ReductionOp.isUsable())
19338 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19339 /*DiscardedValue*/ false);
19340 if (!ReductionOp.isUsable())
19341 continue;
19342 }
19343
19344 // Add copy operations for inscan reductions.
19345 // LHS = RHS;
19346 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19347 if (ClauseKind == OMPC_reduction &&
19348 RD.RedModifier == OMPC_REDUCTION_inscan) {
19349 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19350 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19351 RHS.get());
19352 if (!CopyOpRes.isUsable())
19353 continue;
19354 CopyOpRes =
19355 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19356 if (!CopyOpRes.isUsable())
19357 continue;
19358 // For simd directive and simd-based directives in simd mode no need to
19359 // construct temp array, need just a single temp element.
19360 if (Stack->getCurrentDirective() == OMPD_simd ||
19361 (S.getLangOpts().OpenMPSimd &&
19362 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19363 VarDecl *TempArrayVD =
19364 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19365 D->hasAttrs() ? &D->getAttrs() : nullptr);
19366 // Add a constructor to the temp decl.
19367 S.ActOnUninitializedDecl(TempArrayVD);
19368 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19369 } else {
19370 // Build temp array for prefix sum.
19371 auto *Dim = new (S.Context)
19373 QualType ArrayTy =
19375 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19376 VarDecl *TempArrayVD =
19377 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19378 D->hasAttrs() ? &D->getAttrs() : nullptr);
19379 // Add a constructor to the temp decl.
19380 S.ActOnUninitializedDecl(TempArrayVD);
19381 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19382 TempArrayElem =
19383 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19384 auto *Idx = new (S.Context)
19386 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19387 ELoc, Idx, ELoc);
19388 }
19389 }
19390
19391 // OpenMP [2.15.4.6, Restrictions, p.2]
19392 // A list item that appears in an in_reduction clause of a task construct
19393 // must appear in a task_reduction clause of a construct associated with a
19394 // taskgroup region that includes the participating task in its taskgroup
19395 // set. The construct associated with the innermost region that meets this
19396 // condition must specify the same reduction-identifier as the in_reduction
19397 // clause.
19398 if (ClauseKind == OMPC_in_reduction) {
19399 SourceRange ParentSR;
19400 BinaryOperatorKind ParentBOK;
19401 const Expr *ParentReductionOp = nullptr;
19402 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19403 DSAStackTy::DSAVarData ParentBOKDSA =
19404 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19405 ParentBOKTD);
19406 DSAStackTy::DSAVarData ParentReductionOpDSA =
19407 Stack->getTopMostTaskgroupReductionData(
19408 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19409 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19410 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19411 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19412 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19413 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19414 bool EmitError = true;
19415 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19416 llvm::FoldingSetNodeID RedId, ParentRedId;
19417 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19418 DeclareReductionRef.get()->Profile(RedId, Context,
19419 /*Canonical=*/true);
19420 EmitError = RedId != ParentRedId;
19421 }
19422 if (EmitError) {
19423 S.Diag(ReductionId.getBeginLoc(),
19424 diag::err_omp_reduction_identifier_mismatch)
19425 << ReductionIdRange << RefExpr->getSourceRange();
19426 S.Diag(ParentSR.getBegin(),
19427 diag::note_omp_previous_reduction_identifier)
19428 << ParentSR
19429 << (IsParentBOK ? ParentBOKDSA.RefExpr
19430 : ParentReductionOpDSA.RefExpr)
19431 ->getSourceRange();
19432 continue;
19433 }
19434 }
19435 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19436 }
19437
19438 DeclRefExpr *Ref = nullptr;
19439 Expr *VarsExpr = RefExpr->IgnoreParens();
19440 if (!VD && !S.CurContext->isDependentContext()) {
19441 if (ASE || OASE) {
19442 TransformExprToCaptures RebuildToCapture(S, D);
19443 VarsExpr =
19444 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19445 Ref = RebuildToCapture.getCapturedExpr();
19446 } else {
19447 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19448 }
19449 if (!S.isOpenMPCapturedDecl(D)) {
19450 RD.ExprCaptures.emplace_back(Ref->getDecl());
19451 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19452 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19453 if (!RefRes.isUsable())
19454 continue;
19455 ExprResult PostUpdateRes =
19456 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19457 RefRes.get());
19458 if (!PostUpdateRes.isUsable())
19459 continue;
19460 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19461 Stack->getCurrentDirective() == OMPD_taskgroup) {
19462 S.Diag(RefExpr->getExprLoc(),
19463 diag::err_omp_reduction_non_addressable_expression)
19464 << RefExpr->getSourceRange();
19465 continue;
19466 }
19467 RD.ExprPostUpdates.emplace_back(
19468 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19469 }
19470 }
19471 }
19472 // All reduction items are still marked as reduction (to do not increase
19473 // code base size).
19474 unsigned Modifier = RD.RedModifier;
19475 // Consider task_reductions as reductions with task modifier. Required for
19476 // correct analysis of in_reduction clauses.
19477 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19478 Modifier = OMPC_REDUCTION_task;
19479 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19480 ASE || OASE);
19481 if (Modifier == OMPC_REDUCTION_task &&
19482 (CurrDir == OMPD_taskgroup ||
19483 ((isOpenMPParallelDirective(CurrDir) ||
19484 isOpenMPWorksharingDirective(CurrDir)) &&
19485 !isOpenMPSimdDirective(CurrDir)))) {
19486 if (DeclareReductionRef.isUsable())
19487 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19488 DeclareReductionRef.get());
19489 else
19490 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19491 }
19492 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19493 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19494 TempArrayElem.get());
19495 }
19496 return RD.Vars.empty();
19497}
19498
19501 SourceLocation StartLoc, SourceLocation LParenLoc,
19502 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19503 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19504 ArrayRef<Expr *> UnresolvedReductions) {
19505 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19506 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19507 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19508 /*Last=*/OMPC_REDUCTION_unknown)
19509 << getOpenMPClauseName(OMPC_reduction);
19510 return nullptr;
19511 }
19512 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19513 // A reduction clause with the inscan reduction-modifier may only appear on a
19514 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19515 // construct, a parallel worksharing-loop construct or a parallel
19516 // worksharing-loop SIMD construct.
19517 if (Modifier == OMPC_REDUCTION_inscan &&
19518 (DSAStack->getCurrentDirective() != OMPD_for &&
19519 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19520 DSAStack->getCurrentDirective() != OMPD_simd &&
19521 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19522 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19523 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19524 return nullptr;
19525 }
19526
19527 ReductionData RD(VarList.size(), Modifier);
19528 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
19529 StartLoc, LParenLoc, ColonLoc, EndLoc,
19530 ReductionIdScopeSpec, ReductionId,
19531 UnresolvedReductions, RD))
19532 return nullptr;
19533
19535 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
19536 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19537 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19538 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19539 buildPreInits(Context, RD.ExprCaptures),
19540 buildPostUpdate(*this, RD.ExprPostUpdates));
19541}
19542
19544 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19545 SourceLocation ColonLoc, SourceLocation EndLoc,
19546 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19547 ArrayRef<Expr *> UnresolvedReductions) {
19548 ReductionData RD(VarList.size());
19549 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
19550 StartLoc, LParenLoc, ColonLoc, EndLoc,
19551 ReductionIdScopeSpec, ReductionId,
19552 UnresolvedReductions, RD))
19553 return nullptr;
19554
19556 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19557 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19558 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19559 buildPreInits(Context, RD.ExprCaptures),
19560 buildPostUpdate(*this, RD.ExprPostUpdates));
19561}
19562
19564 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19565 SourceLocation ColonLoc, SourceLocation EndLoc,
19566 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19567 ArrayRef<Expr *> UnresolvedReductions) {
19568 ReductionData RD(VarList.size());
19569 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
19570 StartLoc, LParenLoc, ColonLoc, EndLoc,
19571 ReductionIdScopeSpec, ReductionId,
19572 UnresolvedReductions, RD))
19573 return nullptr;
19574
19576 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19577 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19578 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19579 buildPreInits(Context, RD.ExprCaptures),
19580 buildPostUpdate(*this, RD.ExprPostUpdates));
19581}
19582
19584 SourceLocation LinLoc) {
19585 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19586 LinKind == OMPC_LINEAR_unknown) {
19587 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
19588 return true;
19589 }
19590 return false;
19591}
19592
19595 bool IsDeclareSimd) {
19596 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19597 // A variable must not have an incomplete type or a reference type.
19598 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
19599 return true;
19600 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19601 !Type->isReferenceType()) {
19602 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19603 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19604 return true;
19605 }
19606 Type = Type.getNonReferenceType();
19607
19608 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19609 // A variable that is privatized must not have a const-qualified type
19610 // unless it is of class type with a mutable member. This restriction does
19611 // not apply to the firstprivate clause, nor to the linear clause on
19612 // declarative directives (like declare simd).
19613 if (!IsDeclareSimd &&
19614 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
19615 return true;
19616
19617 // A list item must be of integral or pointer type.
19618 Type = Type.getUnqualifiedType().getCanonicalType();
19619 const auto *Ty = Type.getTypePtrOrNull();
19620 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19621 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
19622 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19623 if (D) {
19624 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19626 Diag(D->getLocation(),
19627 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19628 << D;
19629 }
19630 return true;
19631 }
19632 return false;
19633}
19634
19636 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19637 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19638 SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19640 SmallVector<Expr *, 8> Privates;
19642 SmallVector<Decl *, 4> ExprCaptures;
19643 SmallVector<Expr *, 4> ExprPostUpdates;
19644 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19645 LinKind = OMPC_LINEAR_val;
19646 for (Expr *RefExpr : VarList) {
19647 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19648 SourceLocation ELoc;
19649 SourceRange ERange;
19650 Expr *SimpleRefExpr = RefExpr;
19651 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
19652 if (Res.second) {
19653 // It will be analyzed later.
19654 Vars.push_back(RefExpr);
19655 Privates.push_back(nullptr);
19656 Inits.push_back(nullptr);
19657 }
19658 ValueDecl *D = Res.first;
19659 if (!D)
19660 continue;
19661
19662 QualType Type = D->getType();
19663 auto *VD = dyn_cast<VarDecl>(D);
19664
19665 // OpenMP [2.14.3.7, linear clause]
19666 // A list-item cannot appear in more than one linear clause.
19667 // A list-item that appears in a linear clause cannot appear in any
19668 // other data-sharing attribute clause.
19669 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19670 if (DVar.RefExpr) {
19671 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19672 << getOpenMPClauseName(OMPC_linear);
19673 reportOriginalDsa(*this, DSAStack, D, DVar);
19674 continue;
19675 }
19676
19677 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19678 continue;
19679 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19680
19681 // Build private copy of original var.
19682 VarDecl *Private =
19683 buildVarDecl(*this, ELoc, Type, D->getName(),
19684 D->hasAttrs() ? &D->getAttrs() : nullptr,
19685 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19686 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
19687 // Build var to save initial value.
19688 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
19689 Expr *InitExpr;
19690 DeclRefExpr *Ref = nullptr;
19691 if (!VD && !CurContext->isDependentContext()) {
19692 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
19693 if (!isOpenMPCapturedDecl(D)) {
19694 ExprCaptures.push_back(Ref->getDecl());
19695 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19696 ExprResult RefRes = DefaultLvalueConversion(Ref);
19697 if (!RefRes.isUsable())
19698 continue;
19699 ExprResult PostUpdateRes =
19700 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19701 SimpleRefExpr, RefRes.get());
19702 if (!PostUpdateRes.isUsable())
19703 continue;
19704 ExprPostUpdates.push_back(
19705 IgnoredValueConversions(PostUpdateRes.get()).get());
19706 }
19707 }
19708 }
19709 if (LinKind == OMPC_LINEAR_uval)
19710 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19711 else
19712 InitExpr = VD ? SimpleRefExpr : Ref;
19713 AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
19714 /*DirectInit=*/false);
19715 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
19716
19717 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19718 Vars.push_back((VD || CurContext->isDependentContext())
19719 ? RefExpr->IgnoreParens()
19720 : Ref);
19721 Privates.push_back(PrivateRef);
19722 Inits.push_back(InitRef);
19723 }
19724
19725 if (Vars.empty())
19726 return nullptr;
19727
19728 Expr *StepExpr = Step;
19729 Expr *CalcStepExpr = nullptr;
19730 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19731 !Step->isInstantiationDependent() &&
19733 SourceLocation StepLoc = Step->getBeginLoc();
19735 if (Val.isInvalid())
19736 return nullptr;
19737 StepExpr = Val.get();
19738
19739 // Build var to save the step value.
19740 VarDecl *SaveVar =
19741 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
19742 ExprResult SaveRef =
19743 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
19744 ExprResult CalcStep =
19745 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19746 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
19747
19748 // Warn about zero linear step (it would be probably better specified as
19749 // making corresponding variables 'const').
19751 StepExpr->getIntegerConstantExpr(Context)) {
19752 if (!Result->isNegative() && !Result->isStrictlyPositive())
19753 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19754 << Vars[0] << (Vars.size() > 1);
19755 } else if (CalcStep.isUsable()) {
19756 // Calculate the step beforehand instead of doing this on each iteration.
19757 // (This is not used if the number of iterations may be kfold-ed).
19758 CalcStepExpr = CalcStep.get();
19759 }
19760 }
19761
19762 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
19763 ColonLoc, EndLoc, Vars, Privates, Inits,
19764 StepExpr, CalcStepExpr,
19765 buildPreInits(Context, ExprCaptures),
19766 buildPostUpdate(*this, ExprPostUpdates));
19767}
19768
19770 Expr *NumIterations, Sema &SemaRef,
19771 Scope *S, DSAStackTy *Stack) {
19772 // Walk the vars and build update/final expressions for the CodeGen.
19773 SmallVector<Expr *, 8> Updates;
19775 SmallVector<Expr *, 8> UsedExprs;
19776 Expr *Step = Clause.getStep();
19777 Expr *CalcStep = Clause.getCalcStep();
19778 // OpenMP [2.14.3.7, linear clause]
19779 // If linear-step is not specified it is assumed to be 1.
19780 if (!Step)
19781 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19782 else if (CalcStep)
19783 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19784 bool HasErrors = false;
19785 auto CurInit = Clause.inits().begin();
19786 auto CurPrivate = Clause.privates().begin();
19787 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19788 for (Expr *RefExpr : Clause.varlists()) {
19789 SourceLocation ELoc;
19790 SourceRange ERange;
19791 Expr *SimpleRefExpr = RefExpr;
19792 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19793 ValueDecl *D = Res.first;
19794 if (Res.second || !D) {
19795 Updates.push_back(nullptr);
19796 Finals.push_back(nullptr);
19797 HasErrors = true;
19798 continue;
19799 }
19800 auto &&Info = Stack->isLoopControlVariable(D);
19801 // OpenMP [2.15.11, distribute simd Construct]
19802 // A list item may not appear in a linear clause, unless it is the loop
19803 // iteration variable.
19804 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19805 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19806 SemaRef.Diag(ELoc,
19807 diag::err_omp_linear_distribute_var_non_loop_iteration);
19808 Updates.push_back(nullptr);
19809 Finals.push_back(nullptr);
19810 HasErrors = true;
19811 continue;
19812 }
19813 Expr *InitExpr = *CurInit;
19814
19815 // Build privatized reference to the current linear var.
19816 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19817 Expr *CapturedRef;
19818 if (LinKind == OMPC_LINEAR_uval)
19819 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19820 else
19821 CapturedRef =
19822 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19823 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19824 /*RefersToCapture=*/true);
19825
19826 // Build update: Var = InitExpr + IV * Step
19827 ExprResult Update;
19828 if (!Info.first)
19829 Update = buildCounterUpdate(
19830 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19831 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19832 else
19833 Update = *CurPrivate;
19834 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19835 /*DiscardedValue*/ false);
19836
19837 // Build final: Var = PrivCopy;
19838 ExprResult Final;
19839 if (!Info.first)
19840 Final = SemaRef.BuildBinOp(
19841 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19842 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19843 else
19844 Final = *CurPrivate;
19845 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19846 /*DiscardedValue*/ false);
19847
19848 if (!Update.isUsable() || !Final.isUsable()) {
19849 Updates.push_back(nullptr);
19850 Finals.push_back(nullptr);
19851 UsedExprs.push_back(nullptr);
19852 HasErrors = true;
19853 } else {
19854 Updates.push_back(Update.get());
19855 Finals.push_back(Final.get());
19856 if (!Info.first)
19857 UsedExprs.push_back(SimpleRefExpr);
19858 }
19859 ++CurInit;
19860 ++CurPrivate;
19861 }
19862 if (Expr *S = Clause.getStep())
19863 UsedExprs.push_back(S);
19864 // Fill the remaining part with the nullptr.
19865 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19866 Clause.setUpdates(Updates);
19867 Clause.setFinals(Finals);
19868 Clause.setUsedExprs(UsedExprs);
19869 return HasErrors;
19870}
19871
19873 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19874 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19876 for (Expr *RefExpr : VarList) {
19877 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19878 SourceLocation ELoc;
19879 SourceRange ERange;
19880 Expr *SimpleRefExpr = RefExpr;
19881 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
19882 if (Res.second) {
19883 // It will be analyzed later.
19884 Vars.push_back(RefExpr);
19885 }
19886 ValueDecl *D = Res.first;
19887 if (!D)
19888 continue;
19889
19890 QualType QType = D->getType();
19891 auto *VD = dyn_cast<VarDecl>(D);
19892
19893 // OpenMP [2.8.1, simd construct, Restrictions]
19894 // The type of list items appearing in the aligned clause must be
19895 // array, pointer, reference to array, or reference to pointer.
19897 const Type *Ty = QType.getTypePtrOrNull();
19898 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19899 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19900 << QType << getLangOpts().CPlusPlus << ERange;
19901 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19903 Diag(D->getLocation(),
19904 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19905 << D;
19906 continue;
19907 }
19908
19909 // OpenMP [2.8.1, simd construct, Restrictions]
19910 // A list-item cannot appear in more than one aligned clause.
19911 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19912 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19913 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19914 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19915 << getOpenMPClauseName(OMPC_aligned);
19916 continue;
19917 }
19918
19919 DeclRefExpr *Ref = nullptr;
19920 if (!VD && isOpenMPCapturedDecl(D))
19921 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
19922 Vars.push_back(DefaultFunctionArrayConversion(
19923 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19924 .get());
19925 }
19926
19927 // OpenMP [2.8.1, simd construct, Description]
19928 // The parameter of the aligned clause, alignment, must be a constant
19929 // positive integer expression.
19930 // If no optional parameter is specified, implementation-defined default
19931 // alignments for SIMD instructions on the target platforms are assumed.
19932 if (Alignment != nullptr) {
19933 ExprResult AlignResult =
19934 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19935 if (AlignResult.isInvalid())
19936 return nullptr;
19937 Alignment = AlignResult.get();
19938 }
19939 if (Vars.empty())
19940 return nullptr;
19941
19942 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
19943 EndLoc, Vars, Alignment);
19944}
19945
19947 SourceLocation StartLoc,
19948 SourceLocation LParenLoc,
19949 SourceLocation EndLoc) {
19951 SmallVector<Expr *, 8> SrcExprs;
19952 SmallVector<Expr *, 8> DstExprs;
19953 SmallVector<Expr *, 8> AssignmentOps;
19954 for (Expr *RefExpr : VarList) {
19955 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19956 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19957 // It will be analyzed later.
19958 Vars.push_back(RefExpr);
19959 SrcExprs.push_back(nullptr);
19960 DstExprs.push_back(nullptr);
19961 AssignmentOps.push_back(nullptr);
19962 continue;
19963 }
19964
19965 SourceLocation ELoc = RefExpr->getExprLoc();
19966 // OpenMP [2.1, C/C++]
19967 // A list item is a variable name.
19968 // OpenMP [2.14.4.1, Restrictions, p.1]
19969 // A list item that appears in a copyin clause must be threadprivate.
19970 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19971 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19972 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19973 << 0 << RefExpr->getSourceRange();
19974 continue;
19975 }
19976
19977 Decl *D = DE->getDecl();
19978 auto *VD = cast<VarDecl>(D);
19979
19980 QualType Type = VD->getType();
19982 // It will be analyzed later.
19983 Vars.push_back(DE);
19984 SrcExprs.push_back(nullptr);
19985 DstExprs.push_back(nullptr);
19986 AssignmentOps.push_back(nullptr);
19987 continue;
19988 }
19989
19990 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19991 // A list item that appears in a copyin clause must be threadprivate.
19992 if (!DSAStack->isThreadPrivate(VD)) {
19993 Diag(ELoc, diag::err_omp_required_access)
19994 << getOpenMPClauseName(OMPC_copyin)
19995 << getOpenMPDirectiveName(OMPD_threadprivate);
19996 continue;
19997 }
19998
19999 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20000 // A variable of class type (or array thereof) that appears in a
20001 // copyin clause requires an accessible, unambiguous copy assignment
20002 // operator for the class type.
20004 VarDecl *SrcVD =
20005 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20006 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20007 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20008 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20009 VarDecl *DstVD =
20010 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20011 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20012 DeclRefExpr *PseudoDstExpr =
20013 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20014 // For arrays generate assignment operation for single element and replace
20015 // it by the original array element in CodeGen.
20016 ExprResult AssignmentOp =
20017 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20018 PseudoSrcExpr);
20019 if (AssignmentOp.isInvalid())
20020 continue;
20021 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20022 /*DiscardedValue*/ false);
20023 if (AssignmentOp.isInvalid())
20024 continue;
20025
20026 DSAStack->addDSA(VD, DE, OMPC_copyin);
20027 Vars.push_back(DE);
20028 SrcExprs.push_back(PseudoSrcExpr);
20029 DstExprs.push_back(PseudoDstExpr);
20030 AssignmentOps.push_back(AssignmentOp.get());
20031 }
20032
20033 if (Vars.empty())
20034 return nullptr;
20035
20036 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20037 SrcExprs, DstExprs, AssignmentOps);
20038}
20039
20041 SourceLocation StartLoc,
20042 SourceLocation LParenLoc,
20043 SourceLocation EndLoc) {
20045 SmallVector<Expr *, 8> SrcExprs;
20046 SmallVector<Expr *, 8> DstExprs;
20047 SmallVector<Expr *, 8> AssignmentOps;
20048 for (Expr *RefExpr : VarList) {
20049 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20050 SourceLocation ELoc;
20051 SourceRange ERange;
20052 Expr *SimpleRefExpr = RefExpr;
20053 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20054 if (Res.second) {
20055 // It will be analyzed later.
20056 Vars.push_back(RefExpr);
20057 SrcExprs.push_back(nullptr);
20058 DstExprs.push_back(nullptr);
20059 AssignmentOps.push_back(nullptr);
20060 }
20061 ValueDecl *D = Res.first;
20062 if (!D)
20063 continue;
20064
20065 QualType Type = D->getType();
20066 auto *VD = dyn_cast<VarDecl>(D);
20067
20068 // OpenMP [2.14.4.2, Restrictions, p.2]
20069 // A list item that appears in a copyprivate clause may not appear in a
20070 // private or firstprivate clause on the single construct.
20071 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20072 DSAStackTy::DSAVarData DVar =
20073 DSAStack->getTopDSA(D, /*FromParent=*/false);
20074 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20075 DVar.RefExpr) {
20076 Diag(ELoc, diag::err_omp_wrong_dsa)
20077 << getOpenMPClauseName(DVar.CKind)
20078 << getOpenMPClauseName(OMPC_copyprivate);
20079 reportOriginalDsa(*this, DSAStack, D, DVar);
20080 continue;
20081 }
20082
20083 // OpenMP [2.11.4.2, Restrictions, p.1]
20084 // All list items that appear in a copyprivate clause must be either
20085 // threadprivate or private in the enclosing context.
20086 if (DVar.CKind == OMPC_unknown) {
20087 DVar = DSAStack->getImplicitDSA(D, false);
20088 if (DVar.CKind == OMPC_shared) {
20089 Diag(ELoc, diag::err_omp_required_access)
20090 << getOpenMPClauseName(OMPC_copyprivate)
20091 << "threadprivate or private in the enclosing context";
20092 reportOriginalDsa(*this, DSAStack, D, DVar);
20093 continue;
20094 }
20095 }
20096 }
20097
20098 // Variably modified types are not supported.
20100 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20101 << getOpenMPClauseName(OMPC_copyprivate) << Type
20102 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20103 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20105 Diag(D->getLocation(),
20106 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20107 << D;
20108 continue;
20109 }
20110
20111 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20112 // A variable of class type (or array thereof) that appears in a
20113 // copyin clause requires an accessible, unambiguous copy assignment
20114 // operator for the class type.
20115 Type = Context.getBaseElementType(Type.getNonReferenceType())
20117 VarDecl *SrcVD =
20118 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20119 D->hasAttrs() ? &D->getAttrs() : nullptr);
20120 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20121 VarDecl *DstVD =
20122 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20123 D->hasAttrs() ? &D->getAttrs() : nullptr);
20124 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20125 ExprResult AssignmentOp = BuildBinOp(
20126 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20127 if (AssignmentOp.isInvalid())
20128 continue;
20129 AssignmentOp =
20130 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20131 if (AssignmentOp.isInvalid())
20132 continue;
20133
20134 // No need to mark vars as copyprivate, they are already threadprivate or
20135 // implicitly private.
20136 assert(VD || isOpenMPCapturedDecl(D));
20137 Vars.push_back(
20138 VD ? RefExpr->IgnoreParens()
20139 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20140 SrcExprs.push_back(PseudoSrcExpr);
20141 DstExprs.push_back(PseudoDstExpr);
20142 AssignmentOps.push_back(AssignmentOp.get());
20143 }
20144
20145 if (Vars.empty())
20146 return nullptr;
20147
20148 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20149 Vars, SrcExprs, DstExprs, AssignmentOps);
20150}
20151
20153 SourceLocation StartLoc,
20154 SourceLocation LParenLoc,
20155 SourceLocation EndLoc) {
20156 if (VarList.empty())
20157 return nullptr;
20158
20159 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20160}
20161
20162/// Tries to find omp_depend_t. type.
20163static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20164 bool Diagnose = true) {
20165 QualType OMPDependT = Stack->getOMPDependT();
20166 if (!OMPDependT.isNull())
20167 return true;
20168 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20169 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20170 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20171 if (Diagnose)
20172 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20173 return false;
20174 }
20175 Stack->setOMPDependT(PT.get());
20176 return true;
20177}
20178
20180 SourceLocation LParenLoc,
20181 SourceLocation EndLoc) {
20182 if (!Depobj)
20183 return nullptr;
20184
20185 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
20186
20187 // OpenMP 5.0, 2.17.10.1 depobj Construct
20188 // depobj is an lvalue expression of type omp_depend_t.
20189 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20190 !Depobj->isInstantiationDependent() &&
20192 (OMPDependTFound &&
20193 !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
20194 /*CompareUnqualified=*/true))) {
20195 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20196 << 0 << Depobj->getType() << Depobj->getSourceRange();
20197 }
20198
20199 if (!Depobj->isLValue()) {
20200 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20201 << 1 << Depobj->getSourceRange();
20202 }
20203
20204 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20205}
20206
20207OMPClause *
20209 Expr *DepModifier, ArrayRef<Expr *> VarList,
20210 SourceLocation StartLoc, SourceLocation LParenLoc,
20211 SourceLocation EndLoc) {
20212 OpenMPDependClauseKind DepKind = Data.DepKind;
20213 SourceLocation DepLoc = Data.DepLoc;
20214 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20215 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20216 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20217 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20218 return nullptr;
20219 }
20220 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20221 DepKind == OMPC_DEPEND_mutexinoutset) {
20222 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20223 return nullptr;
20224 }
20225 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20226 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20227 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20228 DepKind == OMPC_DEPEND_sink ||
20229 ((LangOpts.OpenMP < 50 ||
20230 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20231 DepKind == OMPC_DEPEND_depobj))) {
20232 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20233 OMPC_DEPEND_outallmemory,
20234 OMPC_DEPEND_inoutallmemory};
20235 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
20236 Except.push_back(OMPC_DEPEND_depobj);
20237 if (LangOpts.OpenMP < 51)
20238 Except.push_back(OMPC_DEPEND_inoutset);
20239 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
20240 ? "depend modifier(iterator) or "
20241 : "";
20242 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20243 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20244 /*Last=*/OMPC_DEPEND_unknown,
20245 Except)
20246 << getOpenMPClauseName(OMPC_depend);
20247 return nullptr;
20248 }
20249 if (DepModifier &&
20250 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20251 Diag(DepModifier->getExprLoc(),
20252 diag::err_omp_depend_sink_source_with_modifier);
20253 return nullptr;
20254 }
20255 if (DepModifier &&
20256 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20257 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20258
20261 llvm::APSInt DepCounter(/*BitWidth=*/32);
20262 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20263 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20264 if (const Expr *OrderedCountExpr =
20265 DSAStack->getParentOrderedRegionParam().first) {
20266 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
20267 TotalDepCount.setIsUnsigned(/*Val=*/true);
20268 }
20269 }
20270 for (Expr *RefExpr : VarList) {
20271 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20272 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20273 // It will be analyzed later.
20274 Vars.push_back(RefExpr);
20275 continue;
20276 }
20277
20278 SourceLocation ELoc = RefExpr->getExprLoc();
20279 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20280 if (DepKind == OMPC_DEPEND_sink) {
20281 if (DSAStack->getParentOrderedRegionParam().first &&
20282 DepCounter >= TotalDepCount) {
20283 Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20284 continue;
20285 }
20286 ++DepCounter;
20287 // OpenMP [2.13.9, Summary]
20288 // depend(dependence-type : vec), where dependence-type is:
20289 // 'sink' and where vec is the iteration vector, which has the form:
20290 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20291 // where n is the value specified by the ordered clause in the loop
20292 // directive, xi denotes the loop iteration variable of the i-th nested
20293 // loop associated with the loop directive, and di is a constant
20294 // non-negative integer.
20296 // It will be analyzed later.
20297 Vars.push_back(RefExpr);
20298 continue;
20299 }
20300 SimpleExpr = SimpleExpr->IgnoreImplicit();
20302 SourceLocation OOLoc;
20303 Expr *LHS = SimpleExpr;
20304 Expr *RHS = nullptr;
20305 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20306 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20307 OOLoc = BO->getOperatorLoc();
20308 LHS = BO->getLHS()->IgnoreParenImpCasts();
20309 RHS = BO->getRHS()->IgnoreParenImpCasts();
20310 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20311 OOK = OCE->getOperator();
20312 OOLoc = OCE->getOperatorLoc();
20313 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20314 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20315 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20316 OOK = MCE->getMethodDecl()
20317 ->getNameInfo()
20318 .getName()
20319 .getCXXOverloadedOperator();
20320 OOLoc = MCE->getCallee()->getExprLoc();
20321 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20322 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20323 }
20324 SourceLocation ELoc;
20325 SourceRange ERange;
20326 auto Res = getPrivateItem(*this, LHS, ELoc, ERange);
20327 if (Res.second) {
20328 // It will be analyzed later.
20329 Vars.push_back(RefExpr);
20330 }
20331 ValueDecl *D = Res.first;
20332 if (!D)
20333 continue;
20334
20335 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20336 Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20337 continue;
20338 }
20339 if (RHS) {
20340 ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
20341 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20342 if (RHSRes.isInvalid())
20343 continue;
20344 }
20346 DSAStack->getParentOrderedRegionParam().first &&
20347 DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
20348 const ValueDecl *VD =
20349 DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
20350 if (VD)
20351 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20352 << 1 << VD;
20353 else
20354 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
20355 continue;
20356 }
20357 OpsOffs.emplace_back(RHS, OOK);
20358 } else {
20359 bool OMPDependTFound = LangOpts.OpenMP >= 50;
20360 if (OMPDependTFound)
20361 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
20362 DepKind == OMPC_DEPEND_depobj);
20363 if (DepKind == OMPC_DEPEND_depobj) {
20364 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20365 // List items used in depend clauses with the depobj dependence type
20366 // must be expressions of the omp_depend_t type.
20367 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20368 !RefExpr->isInstantiationDependent() &&
20369 !RefExpr->containsUnexpandedParameterPack() &&
20370 (OMPDependTFound &&
20371 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
20372 RefExpr->getType()))) {
20373 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20374 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20375 continue;
20376 }
20377 if (!RefExpr->isLValue()) {
20378 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20379 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20380 continue;
20381 }
20382 } else {
20383 // OpenMP 5.0 [2.17.11, Restrictions]
20384 // List items used in depend clauses cannot be zero-length array
20385 // sections.
20386 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20387 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
20388 if (OASE) {
20389 QualType BaseType =
20391 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20392 ExprTy = ATy->getElementType();
20393 else
20394 ExprTy = BaseType->getPointeeType();
20395 ExprTy = ExprTy.getNonReferenceType();
20396 const Expr *Length = OASE->getLength();
20398 if (Length && !Length->isValueDependent() &&
20399 Length->EvaluateAsInt(Result, Context) &&
20400 Result.Val.getInt().isZero()) {
20401 Diag(ELoc,
20402 diag::err_omp_depend_zero_length_array_section_not_allowed)
20403 << SimpleExpr->getSourceRange();
20404 continue;
20405 }
20406 }
20407
20408 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20409 // List items used in depend clauses with the in, out, inout,
20410 // inoutset, or mutexinoutset dependence types cannot be
20411 // expressions of the omp_depend_t type.
20412 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20413 !RefExpr->isInstantiationDependent() &&
20414 !RefExpr->containsUnexpandedParameterPack() &&
20415 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20416 (OMPDependTFound &&
20417 DSAStack->getOMPDependT().getTypePtr() == ExprTy.getTypePtr()))) {
20418 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20419 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20420 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20421 continue;
20422 }
20423
20424 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20425 if (ASE && !ASE->getBase()->isTypeDependent() &&
20426 !ASE->getBase()->getType().getNonReferenceType()->isPointerType() &&
20427 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20428 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20429 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20430 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20431 continue;
20432 }
20433
20434 ExprResult Res;
20435 {
20436 Sema::TentativeAnalysisScope Trap(*this);
20437 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20438 RefExpr->IgnoreParenImpCasts());
20439 }
20440 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
20441 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20442 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20443 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20444 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20445 continue;
20446 }
20447 }
20448 }
20449 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20450 }
20451
20452 if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
20453 TotalDepCount > VarList.size() &&
20454 DSAStack->getParentOrderedRegionParam().first &&
20455 DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
20456 Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20457 << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
20458 }
20459 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20460 DepKind != OMPC_DEPEND_outallmemory &&
20461 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20462 return nullptr;
20463
20464 auto *C = OMPDependClause::Create(
20465 Context, StartLoc, LParenLoc, EndLoc,
20466 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20467 TotalDepCount.getZExtValue());
20468 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20469 DSAStack->isParentOrderedRegion())
20470 DSAStack->addDoacrossDependClause(C, OpsOffs);
20471 return C;
20472}
20473
20475 Expr *Device, SourceLocation StartLoc,
20476 SourceLocation LParenLoc,
20477 SourceLocation ModifierLoc,
20478 SourceLocation EndLoc) {
20479 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
20480 "Unexpected device modifier in OpenMP < 50.");
20481
20482 bool ErrorFound = false;
20483 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20484 std::string Values =
20485 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20486 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20487 << Values << getOpenMPClauseName(OMPC_device);
20488 ErrorFound = true;
20489 }
20490
20491 Expr *ValExpr = Device;
20492 Stmt *HelperValStmt = nullptr;
20493
20494 // OpenMP [2.9.1, Restrictions]
20495 // The device expression must evaluate to a non-negative integer value.
20496 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
20497 /*StrictlyPositive=*/false) ||
20498 ErrorFound;
20499 if (ErrorFound)
20500 return nullptr;
20501
20502 // OpenMP 5.0 [2.12.5, Restrictions]
20503 // In case of ancestor device-modifier, a requires directive with
20504 // the reverse_offload clause must be specified.
20505 if (Modifier == OMPC_DEVICE_ancestor) {
20506 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20507 targetDiag(
20508 StartLoc,
20509 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20510 ErrorFound = true;
20511 }
20512 }
20513
20514 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20515 OpenMPDirectiveKind CaptureRegion =
20516 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
20517 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
20518 ValExpr = MakeFullExpr(ValExpr).get();
20519 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20520 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
20521 HelperValStmt = buildPreInits(Context, Captures);
20522 }
20523
20524 return new (Context)
20525 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20526 LParenLoc, ModifierLoc, EndLoc);
20527}
20528
20530 DSAStackTy *Stack, QualType QTy,
20531 bool FullCheck = true) {
20532 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20533 return false;
20534 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20535 !QTy.isTriviallyCopyableType(SemaRef.Context))
20536 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20537 return true;
20538}
20539
20540/// Return true if it can be proven that the provided array expression
20541/// (array section or array subscript) does NOT specify the whole size of the
20542/// array whose base type is \a BaseQTy.
20544 const Expr *E,
20545 QualType BaseQTy) {
20546 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20547
20548 // If this is an array subscript, it refers to the whole size if the size of
20549 // the dimension is constant and equals 1. Also, an array section assumes the
20550 // format of an array subscript if no colon is used.
20551 if (isa<ArraySubscriptExpr>(E) ||
20552 (OASE && OASE->getColonLocFirst().isInvalid())) {
20553 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20554 return ATy->getSize().getSExtValue() != 1;
20555 // Size can't be evaluated statically.
20556 return false;
20557 }
20558
20559 assert(OASE && "Expecting array section if not an array subscript.");
20560 const Expr *LowerBound = OASE->getLowerBound();
20561 const Expr *Length = OASE->getLength();
20562
20563 // If there is a lower bound that does not evaluates to zero, we are not
20564 // covering the whole dimension.
20565 if (LowerBound) {
20567 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20568 return false; // Can't get the integer value as a constant.
20569
20570 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20571 if (ConstLowerBound.getSExtValue())
20572 return true;
20573 }
20574
20575 // If we don't have a length we covering the whole dimension.
20576 if (!Length)
20577 return false;
20578
20579 // If the base is a pointer, we don't have a way to get the size of the
20580 // pointee.
20581 if (BaseQTy->isPointerType())
20582 return false;
20583
20584 // We can only check if the length is the same as the size of the dimension
20585 // if we have a constant array.
20586 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20587 if (!CATy)
20588 return false;
20589
20591 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20592 return false; // Can't get the integer value as a constant.
20593
20594 llvm::APSInt ConstLength = Result.Val.getInt();
20595 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
20596}
20597
20598// Return true if it can be proven that the provided array expression (array
20599// section or array subscript) does NOT specify a single element of the array
20600// whose base type is \a BaseQTy.
20602 const Expr *E,
20603 QualType BaseQTy) {
20604 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20605
20606 // An array subscript always refer to a single element. Also, an array section
20607 // assumes the format of an array subscript if no colon is used.
20608 if (isa<ArraySubscriptExpr>(E) ||
20609 (OASE && OASE->getColonLocFirst().isInvalid()))
20610 return false;
20611
20612 assert(OASE && "Expecting array section if not an array subscript.");
20613 const Expr *Length = OASE->getLength();
20614
20615 // If we don't have a length we have to check if the array has unitary size
20616 // for this dimension. Also, we should always expect a length if the base type
20617 // is pointer.
20618 if (!Length) {
20619 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20620 return ATy->getSize().getSExtValue() != 1;
20621 // We cannot assume anything.
20622 return false;
20623 }
20624
20625 // Check if the length evaluates to 1.
20627 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20628 return false; // Can't get the integer value as a constant.
20629
20630 llvm::APSInt ConstLength = Result.Val.getInt();
20631 return ConstLength.getSExtValue() != 1;
20632}
20633
20634// The base of elements of list in a map clause have to be either:
20635// - a reference to variable or field.
20636// - a member expression.
20637// - an array expression.
20638//
20639// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20640// reference to 'r'.
20641//
20642// If we have:
20643//
20644// struct SS {
20645// Bla S;
20646// foo() {
20647// #pragma omp target map (S.Arr[:12]);
20648// }
20649// }
20650//
20651// We want to retrieve the member expression 'this->S';
20652
20653// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20654// If a list item is an array section, it must specify contiguous storage.
20655//
20656// For this restriction it is sufficient that we make sure only references
20657// to variables or fields and array expressions, and that no array sections
20658// exist except in the rightmost expression (unless they cover the whole
20659// dimension of the array). E.g. these would be invalid:
20660//
20661// r.ArrS[3:5].Arr[6:7]
20662//
20663// r.ArrS[3:5].x
20664//
20665// but these would be valid:
20666// r.ArrS[3].Arr[6:7]
20667//
20668// r.ArrS[3].x
20669namespace {
20670class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20671 Sema &SemaRef;
20672 OpenMPClauseKind CKind = OMPC_unknown;
20673 OpenMPDirectiveKind DKind = OMPD_unknown;
20675 bool IsNonContiguous = false;
20676 bool NoDiagnose = false;
20677 const Expr *RelevantExpr = nullptr;
20678 bool AllowUnitySizeArraySection = true;
20679 bool AllowWholeSizeArraySection = true;
20680 bool AllowAnotherPtr = true;
20681 SourceLocation ELoc;
20682 SourceRange ERange;
20683
20684 void emitErrorMsg() {
20685 // If nothing else worked, this is not a valid map clause expression.
20686 if (SemaRef.getLangOpts().OpenMP < 50) {
20687 SemaRef.Diag(ELoc,
20688 diag::err_omp_expected_named_var_member_or_array_expression)
20689 << ERange;
20690 } else {
20691 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20692 << getOpenMPClauseName(CKind) << ERange;
20693 }
20694 }
20695
20696public:
20697 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20698 if (!isa<VarDecl>(DRE->getDecl())) {
20699 emitErrorMsg();
20700 return false;
20701 }
20702 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20703 RelevantExpr = DRE;
20704 // Record the component.
20705 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20706 return true;
20707 }
20708
20709 bool VisitMemberExpr(MemberExpr *ME) {
20710 Expr *E = ME;
20711 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20712
20713 if (isa<CXXThisExpr>(BaseE)) {
20714 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20715 // We found a base expression: this->Val.
20716 RelevantExpr = ME;
20717 } else {
20718 E = BaseE;
20719 }
20720
20721 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20722 if (!NoDiagnose) {
20723 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20724 << ME->getSourceRange();
20725 return false;
20726 }
20727 if (RelevantExpr)
20728 return false;
20729 return Visit(E);
20730 }
20731
20732 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20733
20734 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20735 // A bit-field cannot appear in a map clause.
20736 //
20737 if (FD->isBitField()) {
20738 if (!NoDiagnose) {
20739 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20740 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20741 return false;
20742 }
20743 if (RelevantExpr)
20744 return false;
20745 return Visit(E);
20746 }
20747
20748 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20749 // If the type of a list item is a reference to a type T then the type
20750 // will be considered to be T for all purposes of this clause.
20751 QualType CurType = BaseE->getType().getNonReferenceType();
20752
20753 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20754 // A list item cannot be a variable that is a member of a structure with
20755 // a union type.
20756 //
20757 if (CurType->isUnionType()) {
20758 if (!NoDiagnose) {
20759 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20760 << ME->getSourceRange();
20761 return false;
20762 }
20763 return RelevantExpr || Visit(E);
20764 }
20765
20766 // If we got a member expression, we should not expect any array section
20767 // before that:
20768 //
20769 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20770 // If a list item is an element of a structure, only the rightmost symbol
20771 // of the variable reference can be an array section.
20772 //
20773 AllowUnitySizeArraySection = false;
20774 AllowWholeSizeArraySection = false;
20775
20776 // Record the component.
20777 Components.emplace_back(ME, FD, IsNonContiguous);
20778 return RelevantExpr || Visit(E);
20779 }
20780
20781 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20782 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20783
20784 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20785 if (!NoDiagnose) {
20786 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20787 << 0 << AE->getSourceRange();
20788 return false;
20789 }
20790 return RelevantExpr || Visit(E);
20791 }
20792
20793 // If we got an array subscript that express the whole dimension we
20794 // can have any array expressions before. If it only expressing part of
20795 // the dimension, we can only have unitary-size array expressions.
20797 AllowWholeSizeArraySection = false;
20798
20799 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20800 Expr::EvalResult Result;
20801 if (!AE->getIdx()->isValueDependent() &&
20802 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20803 !Result.Val.getInt().isZero()) {
20804 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20805 diag::err_omp_invalid_map_this_expr);
20806 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20807 diag::note_omp_invalid_subscript_on_this_ptr_map);
20808 }
20809 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20810 RelevantExpr = TE;
20811 }
20812
20813 // Record the component - we don't have any declaration associated.
20814 Components.emplace_back(AE, nullptr, IsNonContiguous);
20815
20816 return RelevantExpr || Visit(E);
20817 }
20818
20819 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
20820 // After OMP 5.0 Array section in reduction clause will be implicitly
20821 // mapped
20822 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20823 "Array sections cannot be implicitly mapped.");
20824 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20825 QualType CurType =
20827
20828 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20829 // If the type of a list item is a reference to a type T then the type
20830 // will be considered to be T for all purposes of this clause.
20831 if (CurType->isReferenceType())
20832 CurType = CurType->getPointeeType();
20833
20834 bool IsPointer = CurType->isAnyPointerType();
20835
20836 if (!IsPointer && !CurType->isArrayType()) {
20837 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20838 << 0 << OASE->getSourceRange();
20839 return false;
20840 }
20841
20842 bool NotWhole =
20843 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20844 bool NotUnity =
20845 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20846
20847 if (AllowWholeSizeArraySection) {
20848 // Any array section is currently allowed. Allowing a whole size array
20849 // section implies allowing a unity array section as well.
20850 //
20851 // If this array section refers to the whole dimension we can still
20852 // accept other array sections before this one, except if the base is a
20853 // pointer. Otherwise, only unitary sections are accepted.
20854 if (NotWhole || IsPointer)
20855 AllowWholeSizeArraySection = false;
20856 } else if (DKind == OMPD_target_update &&
20857 SemaRef.getLangOpts().OpenMP >= 50) {
20858 if (IsPointer && !AllowAnotherPtr)
20859 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20860 << /*array of unknown bound */ 1;
20861 else
20862 IsNonContiguous = true;
20863 } else if (AllowUnitySizeArraySection && NotUnity) {
20864 // A unity or whole array section is not allowed and that is not
20865 // compatible with the properties of the current array section.
20866 if (NoDiagnose)
20867 return false;
20868 SemaRef.Diag(ELoc,
20869 diag::err_array_section_does_not_specify_contiguous_storage)
20870 << OASE->getSourceRange();
20871 return false;
20872 }
20873
20874 if (IsPointer)
20875 AllowAnotherPtr = false;
20876
20877 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20878 Expr::EvalResult ResultR;
20879 Expr::EvalResult ResultL;
20880 if (!OASE->getLength()->isValueDependent() &&
20881 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20882 !ResultR.Val.getInt().isOne()) {
20883 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20884 diag::err_omp_invalid_map_this_expr);
20885 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20886 diag::note_omp_invalid_length_on_this_ptr_mapping);
20887 }
20888 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20889 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20890 SemaRef.getASTContext()) &&
20891 !ResultL.Val.getInt().isZero()) {
20892 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20893 diag::err_omp_invalid_map_this_expr);
20894 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20895 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20896 }
20897 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20898 RelevantExpr = TE;
20899 }
20900
20901 // Record the component - we don't have any declaration associated.
20902 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20903 return RelevantExpr || Visit(E);
20904 }
20905 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20906 Expr *Base = E->getBase();
20907
20908 // Record the component - we don't have any declaration associated.
20909 Components.emplace_back(E, nullptr, IsNonContiguous);
20910
20911 return Visit(Base->IgnoreParenImpCasts());
20912 }
20913
20914 bool VisitUnaryOperator(UnaryOperator *UO) {
20915 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20916 UO->getOpcode() != UO_Deref) {
20917 emitErrorMsg();
20918 return false;
20919 }
20920 if (!RelevantExpr) {
20921 // Record the component if haven't found base decl.
20922 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20923 }
20924 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20925 }
20926 bool VisitBinaryOperator(BinaryOperator *BO) {
20927 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20928 emitErrorMsg();
20929 return false;
20930 }
20931
20932 // Pointer arithmetic is the only thing we expect to happen here so after we
20933 // make sure the binary operator is a pointer type, the we only thing need
20934 // to to is to visit the subtree that has the same type as root (so that we
20935 // know the other subtree is just an offset)
20936 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20937 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20938 Components.emplace_back(BO, nullptr, false);
20939 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20940 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20941 "Either LHS or RHS have base decl inside");
20942 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20943 return RelevantExpr || Visit(LE);
20944 return RelevantExpr || Visit(RE);
20945 }
20946 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20947 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20948 RelevantExpr = CTE;
20949 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20950 return true;
20951 }
20952 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20953 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20954 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20955 return true;
20956 }
20957 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20958 Expr *Source = E->getSourceExpr();
20959 if (!Source) {
20960 emitErrorMsg();
20961 return false;
20962 }
20963 return Visit(Source);
20964 }
20965 bool VisitStmt(Stmt *) {
20966 emitErrorMsg();
20967 return false;
20968 }
20969 const Expr *getFoundBase() const { return RelevantExpr; }
20970 explicit MapBaseChecker(
20971 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20973 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20974 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20975 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20976};
20977} // namespace
20978
20979/// Return the expression of the base of the mappable expression or null if it
20980/// cannot be determined and do all the necessary checks to see if the
20981/// expression is valid as a standalone mappable expression. In the process,
20982/// record all the components of the expression.
20984 Sema &SemaRef, Expr *E,
20986 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20987 SourceLocation ELoc = E->getExprLoc();
20988 SourceRange ERange = E->getSourceRange();
20989 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20990 ERange);
20991 if (Checker.Visit(E->IgnoreParens())) {
20992 // Check if the highest dimension array section has length specified
20993 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20994 (CKind == OMPC_to || CKind == OMPC_from)) {
20995 auto CI = CurComponents.rbegin();
20996 auto CE = CurComponents.rend();
20997 for (; CI != CE; ++CI) {
20998 const auto *OASE =
20999 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21000 if (!OASE)
21001 continue;
21002 if (OASE && OASE->getLength())
21003 break;
21004 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21005 << ERange;
21006 }
21007 }
21008 return Checker.getFoundBase();
21009 }
21010 return nullptr;
21011}
21012
21013// Return true if expression E associated with value VD has conflicts with other
21014// map information.
21016 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21017 bool CurrentRegionOnly,
21019 OpenMPClauseKind CKind) {
21020 assert(VD && E);
21021 SourceLocation ELoc = E->getExprLoc();
21022 SourceRange ERange = E->getSourceRange();
21023
21024 // In order to easily check the conflicts we need to match each component of
21025 // the expression under test with the components of the expressions that are
21026 // already in the stack.
21027
21028 assert(!CurComponents.empty() && "Map clause expression with no components!");
21029 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21030 "Map clause expression with unexpected base!");
21031
21032 // Variables to help detecting enclosing problems in data environment nests.
21033 bool IsEnclosedByDataEnvironmentExpr = false;
21034 const Expr *EnclosingExpr = nullptr;
21035
21036 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21037 VD, CurrentRegionOnly,
21038 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21039 ERange, CKind, &EnclosingExpr,
21041 StackComponents,
21042 OpenMPClauseKind Kind) {
21043 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21044 return false;
21045 assert(!StackComponents.empty() &&
21046 "Map clause expression with no components!");
21047 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21048 "Map clause expression with unexpected base!");
21049 (void)VD;
21050
21051 // The whole expression in the stack.
21052 const Expr *RE = StackComponents.front().getAssociatedExpression();
21053
21054 // Expressions must start from the same base. Here we detect at which
21055 // point both expressions diverge from each other and see if we can
21056 // detect if the memory referred to both expressions is contiguous and
21057 // do not overlap.
21058 auto CI = CurComponents.rbegin();
21059 auto CE = CurComponents.rend();
21060 auto SI = StackComponents.rbegin();
21061 auto SE = StackComponents.rend();
21062 for (; CI != CE && SI != SE; ++CI, ++SI) {
21063
21064 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21065 // At most one list item can be an array item derived from a given
21066 // variable in map clauses of the same construct.
21067 if (CurrentRegionOnly &&
21068 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21069 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21070 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21071 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21072 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21073 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21074 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21075 diag::err_omp_multiple_array_items_in_map_clause)
21076 << CI->getAssociatedExpression()->getSourceRange();
21077 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21078 diag::note_used_here)
21079 << SI->getAssociatedExpression()->getSourceRange();
21080 return true;
21081 }
21082
21083 // Do both expressions have the same kind?
21084 if (CI->getAssociatedExpression()->getStmtClass() !=
21085 SI->getAssociatedExpression()->getStmtClass())
21086 break;
21087
21088 // Are we dealing with different variables/fields?
21089 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21090 break;
21091 }
21092 // Check if the extra components of the expressions in the enclosing
21093 // data environment are redundant for the current base declaration.
21094 // If they are, the maps completely overlap, which is legal.
21095 for (; SI != SE; ++SI) {
21096 QualType Type;
21097 if (const auto *ASE =
21098 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21099 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21100 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21101 SI->getAssociatedExpression())) {
21102 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21103 Type =
21105 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21106 SI->getAssociatedExpression())) {
21107 Type = OASE->getBase()->getType()->getPointeeType();
21108 }
21109 if (Type.isNull() || Type->isAnyPointerType() ||
21111 SemaRef, SI->getAssociatedExpression(), Type))
21112 break;
21113 }
21114
21115 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21116 // List items of map clauses in the same construct must not share
21117 // original storage.
21118 //
21119 // If the expressions are exactly the same or one is a subset of the
21120 // other, it means they are sharing storage.
21121 if (CI == CE && SI == SE) {
21122 if (CurrentRegionOnly) {
21123 if (CKind == OMPC_map) {
21124 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21125 } else {
21126 assert(CKind == OMPC_to || CKind == OMPC_from);
21127 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21128 << ERange;
21129 }
21130 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21131 << RE->getSourceRange();
21132 return true;
21133 }
21134 // If we find the same expression in the enclosing data environment,
21135 // that is legal.
21136 IsEnclosedByDataEnvironmentExpr = true;
21137 return false;
21138 }
21139
21140 QualType DerivedType =
21141 std::prev(CI)->getAssociatedDeclaration()->getType();
21142 SourceLocation DerivedLoc =
21143 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21144
21145 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21146 // If the type of a list item is a reference to a type T then the type
21147 // will be considered to be T for all purposes of this clause.
21148 DerivedType = DerivedType.getNonReferenceType();
21149
21150 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21151 // A variable for which the type is pointer and an array section
21152 // derived from that variable must not appear as list items of map
21153 // clauses of the same construct.
21154 //
21155 // Also, cover one of the cases in:
21156 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21157 // If any part of the original storage of a list item has corresponding
21158 // storage in the device data environment, all of the original storage
21159 // must have corresponding storage in the device data environment.
21160 //
21161 if (DerivedType->isAnyPointerType()) {
21162 if (CI == CE || SI == SE) {
21163 SemaRef.Diag(
21164 DerivedLoc,
21165 diag::err_omp_pointer_mapped_along_with_derived_section)
21166 << DerivedLoc;
21167 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21168 << RE->getSourceRange();
21169 return true;
21170 }
21171 if (CI->getAssociatedExpression()->getStmtClass() !=
21172 SI->getAssociatedExpression()->getStmtClass() ||
21173 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21174 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21175 assert(CI != CE && SI != SE);
21176 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21177 << DerivedLoc;
21178 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21179 << RE->getSourceRange();
21180 return true;
21181 }
21182 }
21183
21184 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21185 // List items of map clauses in the same construct must not share
21186 // original storage.
21187 //
21188 // An expression is a subset of the other.
21189 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21190 if (CKind == OMPC_map) {
21191 if (CI != CE || SI != SE) {
21192 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21193 // a pointer.
21194 auto Begin =
21195 CI != CE ? CurComponents.begin() : StackComponents.begin();
21196 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21197 auto It = Begin;
21198 while (It != End && !It->getAssociatedDeclaration())
21199 std::advance(It, 1);
21200 assert(It != End &&
21201 "Expected at least one component with the declaration.");
21202 if (It != Begin && It->getAssociatedDeclaration()
21203 ->getType()
21204 .getCanonicalType()
21205 ->isAnyPointerType()) {
21206 IsEnclosedByDataEnvironmentExpr = false;
21207 EnclosingExpr = nullptr;
21208 return false;
21209 }
21210 }
21211 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21212 } else {
21213 assert(CKind == OMPC_to || CKind == OMPC_from);
21214 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21215 << ERange;
21216 }
21217 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21218 << RE->getSourceRange();
21219 return true;
21220 }
21221
21222 // The current expression uses the same base as other expression in the
21223 // data environment but does not contain it completely.
21224 if (!CurrentRegionOnly && SI != SE)
21225 EnclosingExpr = RE;
21226
21227 // The current expression is a subset of the expression in the data
21228 // environment.
21229 IsEnclosedByDataEnvironmentExpr |=
21230 (!CurrentRegionOnly && CI != CE && SI == SE);
21231
21232 return false;
21233 });
21234
21235 if (CurrentRegionOnly)
21236 return FoundError;
21237
21238 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21239 // If any part of the original storage of a list item has corresponding
21240 // storage in the device data environment, all of the original storage must
21241 // have corresponding storage in the device data environment.
21242 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21243 // If a list item is an element of a structure, and a different element of
21244 // the structure has a corresponding list item in the device data environment
21245 // prior to a task encountering the construct associated with the map clause,
21246 // then the list item must also have a corresponding list item in the device
21247 // data environment prior to the task encountering the construct.
21248 //
21249 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21250 SemaRef.Diag(ELoc,
21251 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21252 << ERange;
21253 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21254 << EnclosingExpr->getSourceRange();
21255 return true;
21256 }
21257
21258 return FoundError;
21259}
21260
21261// Look up the user-defined mapper given the mapper name and mapped type, and
21262// build a reference to it.
21264 CXXScopeSpec &MapperIdScopeSpec,
21265 const DeclarationNameInfo &MapperId,
21266 QualType Type,
21267 Expr *UnresolvedMapper) {
21268 if (MapperIdScopeSpec.isInvalid())
21269 return ExprError();
21270 // Get the actual type for the array type.
21271 if (Type->isArrayType()) {
21272 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21274 }
21275 // Find all user-defined mappers with the given MapperId.
21276 SmallVector<UnresolvedSet<8>, 4> Lookups;
21277 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21278 Lookup.suppressDiagnostics();
21279 if (S) {
21280 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
21281 NamedDecl *D = Lookup.getRepresentativeDecl();
21282 while (S && !S->isDeclScope(D))
21283 S = S->getParent();
21284 if (S)
21285 S = S->getParent();
21286 Lookups.emplace_back();
21287 Lookups.back().append(Lookup.begin(), Lookup.end());
21288 Lookup.clear();
21289 }
21290 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21291 // Extract the user-defined mappers with the given MapperId.
21292 Lookups.push_back(UnresolvedSet<8>());
21293 for (NamedDecl *D : ULE->decls()) {
21294 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21295 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21296 Lookups.back().addDecl(DMD);
21297 }
21298 }
21299 // Defer the lookup for dependent types. The results will be passed through
21300 // UnresolvedMapper on instantiation.
21301 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21305 return !D->isInvalidDecl() &&
21306 (D->getType()->isDependentType() ||
21307 D->getType()->isInstantiationDependentType() ||
21308 D->getType()->containsUnexpandedParameterPack());
21309 })) {
21310 UnresolvedSet<8> URS;
21311 for (const UnresolvedSet<8> &Set : Lookups) {
21312 if (Set.empty())
21313 continue;
21314 URS.append(Set.begin(), Set.end());
21315 }
21317 SemaRef.Context, /*NamingClass=*/nullptr,
21318 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21319 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
21320 }
21321 SourceLocation Loc = MapperId.getLoc();
21322 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21323 // The type must be of struct, union or class type in C and C++
21325 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21326 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21327 return ExprError();
21328 }
21329 // Perform argument dependent lookup.
21330 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21331 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21332 // Return the first user-defined mapper with the desired type.
21334 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21335 if (!D->isInvalidDecl() &&
21336 SemaRef.Context.hasSameType(D->getType(), Type))
21337 return D;
21338 return nullptr;
21339 }))
21340 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21341 // Find the first user-defined mapper with a type derived from the desired
21342 // type.
21344 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21345 if (!D->isInvalidDecl() &&
21346 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21347 !Type.isMoreQualifiedThan(D->getType()))
21348 return D;
21349 return nullptr;
21350 })) {
21351 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21352 /*DetectVirtual=*/false);
21353 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21354 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21355 VD->getType().getUnqualifiedType()))) {
21356 if (SemaRef.CheckBaseClassAccess(
21357 Loc, VD->getType(), Type, Paths.front(),
21358 /*DiagID=*/0) != Sema::AR_inaccessible) {
21359 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21360 }
21361 }
21362 }
21363 }
21364 // Report error if a mapper is specified, but cannot be found.
21365 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21366 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21367 << Type << MapperId.getName();
21368 return ExprError();
21369 }
21370 return ExprEmpty();
21371}
21372
21373namespace {
21374// Utility struct that gathers all the related lists associated with a mappable
21375// expression.
21376struct MappableVarListInfo {
21377 // The list of expressions.
21378 ArrayRef<Expr *> VarList;
21379 // The list of processed expressions.
21380 SmallVector<Expr *, 16> ProcessedVarList;
21381 // The mappble components for each expression.
21383 // The base declaration of the variable.
21384 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21385 // The reference to the user-defined mapper associated with every expression.
21386 SmallVector<Expr *, 16> UDMapperList;
21387
21388 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21389 // We have a list of components and base declarations for each entry in the
21390 // variable list.
21391 VarComponents.reserve(VarList.size());
21392 VarBaseDeclarations.reserve(VarList.size());
21393 }
21394};
21395} // namespace
21396
21397// Check the validity of the provided variable list for the provided clause kind
21398// \a CKind. In the check process the valid expressions, mappable expression
21399// components, variables, and user-defined mappers are extracted and used to
21400// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21401// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21402// and \a MapperId are expected to be valid if the clause kind is 'map'.
21404 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21405 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21406 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21407 ArrayRef<Expr *> UnresolvedMappers,
21409 ArrayRef<OpenMPMapModifierKind> Modifiers = None,
21410 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21411 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21412 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21413 "Unexpected clause kind with mappable expressions!");
21414
21415 // If the identifier of user-defined mapper is not specified, it is "default".
21416 // We do not change the actual name in this clause to distinguish whether a
21417 // mapper is specified explicitly, i.e., it is not explicitly specified when
21418 // MapperId.getName() is empty.
21419 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21420 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21421 MapperId.setName(DeclNames.getIdentifier(
21422 &SemaRef.getASTContext().Idents.get("default")));
21423 MapperId.setLoc(StartLoc);
21424 }
21425
21426 // Iterators to find the current unresolved mapper expression.
21427 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21428 bool UpdateUMIt = false;
21429 Expr *UnresolvedMapper = nullptr;
21430
21431 bool HasHoldModifier =
21432 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21433
21434 // Keep track of the mappable components and base declarations in this clause.
21435 // Each entry in the list is going to have a list of components associated. We
21436 // record each set of the components so that we can build the clause later on.
21437 // In the end we should have the same amount of declarations and component
21438 // lists.
21439
21440 for (Expr *RE : MVLI.VarList) {
21441 assert(RE && "Null expr in omp to/from/map clause");
21442 SourceLocation ELoc = RE->getExprLoc();
21443
21444 // Find the current unresolved mapper expression.
21445 if (UpdateUMIt && UMIt != UMEnd) {
21446 UMIt++;
21447 assert(
21448 UMIt != UMEnd &&
21449 "Expect the size of UnresolvedMappers to match with that of VarList");
21450 }
21451 UpdateUMIt = true;
21452 if (UMIt != UMEnd)
21453 UnresolvedMapper = *UMIt;
21454
21455 const Expr *VE = RE->IgnoreParenLValueCasts();
21456
21457 if (VE->isValueDependent() || VE->isTypeDependent() ||
21460 // Try to find the associated user-defined mapper.
21462 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21463 VE->getType().getCanonicalType(), UnresolvedMapper);
21464 if (ER.isInvalid())
21465 continue;
21466 MVLI.UDMapperList.push_back(ER.get());
21467 // We can only analyze this information once the missing information is
21468 // resolved.
21469 MVLI.ProcessedVarList.push_back(RE);
21470 continue;
21471 }
21472
21473 Expr *SimpleExpr = RE->IgnoreParenCasts();
21474
21475 if (!RE->isLValue()) {
21476 if (SemaRef.getLangOpts().OpenMP < 50) {
21477 SemaRef.Diag(
21478 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21479 << RE->getSourceRange();
21480 } else {
21481 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21482 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21483 }
21484 continue;
21485 }
21486
21488 ValueDecl *CurDeclaration = nullptr;
21489
21490 // Obtain the array or member expression bases if required. Also, fill the
21491 // components array with all the components identified in the process.
21492 const Expr *BE =
21493 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21494 DSAS->getCurrentDirective(), NoDiagnose);
21495 if (!BE)
21496 continue;
21497
21498 assert(!CurComponents.empty() &&
21499 "Invalid mappable expression information.");
21500
21501 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21502 // Add store "this" pointer to class in DSAStackTy for future checking
21503 DSAS->addMappedClassesQualTypes(TE->getType());
21504 // Try to find the associated user-defined mapper.
21506 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21507 VE->getType().getCanonicalType(), UnresolvedMapper);
21508 if (ER.isInvalid())
21509 continue;
21510 MVLI.UDMapperList.push_back(ER.get());
21511 // Skip restriction checking for variable or field declarations
21512 MVLI.ProcessedVarList.push_back(RE);
21513 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21514 MVLI.VarComponents.back().append(CurComponents.begin(),
21515 CurComponents.end());
21516 MVLI.VarBaseDeclarations.push_back(nullptr);
21517 continue;
21518 }
21519
21520 // For the following checks, we rely on the base declaration which is
21521 // expected to be associated with the last component. The declaration is
21522 // expected to be a variable or a field (if 'this' is being mapped).
21523 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21524 assert(CurDeclaration && "Null decl on map clause.");
21525 assert(
21526 CurDeclaration->isCanonicalDecl() &&
21527 "Expecting components to have associated only canonical declarations.");
21528
21529 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21530 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21531
21532 assert((VD || FD) && "Only variables or fields are expected here!");
21533 (void)FD;
21534
21535 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21536 // threadprivate variables cannot appear in a map clause.
21537 // OpenMP 4.5 [2.10.5, target update Construct]
21538 // threadprivate variables cannot appear in a from clause.
21539 if (VD && DSAS->isThreadPrivate(VD)) {
21540 if (NoDiagnose)
21541 continue;
21542 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21543 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21544 << getOpenMPClauseName(CKind);
21545 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21546 continue;
21547 }
21548
21549 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21550 // A list item cannot appear in both a map clause and a data-sharing
21551 // attribute clause on the same construct.
21552
21553 // Check conflicts with other map clause expressions. We check the conflicts
21554 // with the current construct separately from the enclosing data
21555 // environment, because the restrictions are different. We only have to
21556 // check conflicts across regions for the map clauses.
21557 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21558 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21559 break;
21560 if (CKind == OMPC_map &&
21561 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21562 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21563 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21564 break;
21565
21566 // OpenMP 4.5 [2.10.5, target update Construct]
21567 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21568 // If the type of a list item is a reference to a type T then the type will
21569 // be considered to be T for all purposes of this clause.
21570 auto I = llvm::find_if(
21571 CurComponents,
21573 return MC.getAssociatedDeclaration();
21574 });
21575 assert(I != CurComponents.end() && "Null decl on map clause.");
21576 (void)I;
21577 QualType Type;
21578 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21579 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
21580 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21581 if (ASE) {
21582 Type = ASE->getType().getNonReferenceType();
21583 } else if (OASE) {
21584 QualType BaseType =
21586 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21587 Type = ATy->getElementType();
21588 else
21589 Type = BaseType->getPointeeType();
21590 Type = Type.getNonReferenceType();
21591 } else if (OAShE) {
21592 Type = OAShE->getBase()->getType()->getPointeeType();
21593 } else {
21594 Type = VE->getType();
21595 }
21596
21597 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21598 // A list item in a to or from clause must have a mappable type.
21599 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21600 // A list item must have a mappable type.
21601 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21602 DSAS, Type, /*FullCheck=*/true))
21603 continue;
21604
21605 if (CKind == OMPC_map) {
21606 // target enter data
21607 // OpenMP [2.10.2, Restrictions, p. 99]
21608 // A map-type must be specified in all map clauses and must be either
21609 // to or alloc.
21610 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21611 if (DKind == OMPD_target_enter_data &&
21612 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc)) {
21613 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21614 << (IsMapTypeImplicit ? 1 : 0)
21615 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21616 << getOpenMPDirectiveName(DKind);
21617 continue;
21618 }
21619
21620 // target exit_data
21621 // OpenMP [2.10.3, Restrictions, p. 102]
21622 // A map-type must be specified in all map clauses and must be either
21623 // from, release, or delete.
21624 if (DKind == OMPD_target_exit_data &&
21625 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21626 MapType == OMPC_MAP_delete)) {
21627 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21628 << (IsMapTypeImplicit ? 1 : 0)
21629 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21630 << getOpenMPDirectiveName(DKind);
21631 continue;
21632 }
21633
21634 // The 'ompx_hold' modifier is specifically intended to be used on a
21635 // 'target' or 'target data' directive to prevent data from being unmapped
21636 // during the associated statement. It is not permitted on a 'target
21637 // enter data' or 'target exit data' directive, which have no associated
21638 // statement.
21639 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21640 HasHoldModifier) {
21641 SemaRef.Diag(StartLoc,
21642 diag::err_omp_invalid_map_type_modifier_for_directive)
21644 OMPC_MAP_MODIFIER_ompx_hold)
21645 << getOpenMPDirectiveName(DKind);
21646 continue;
21647 }
21648
21649 // target, target data
21650 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21651 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21652 // A map-type in a map clause must be to, from, tofrom or alloc
21653 if ((DKind == OMPD_target_data ||
21655 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21656 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21657 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21658 << (IsMapTypeImplicit ? 1 : 0)
21659 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21660 << getOpenMPDirectiveName(DKind);
21661 continue;
21662 }
21663
21664 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21665 // A list item cannot appear in both a map clause and a data-sharing
21666 // attribute clause on the same construct
21667 //
21668 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21669 // A list item cannot appear in both a map clause and a data-sharing
21670 // attribute clause on the same construct unless the construct is a
21671 // combined construct.
21672 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21674 DKind == OMPD_target)) {
21675 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21676 if (isOpenMPPrivate(DVar.CKind)) {
21677 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21678 << getOpenMPClauseName(DVar.CKind)
21679 << getOpenMPClauseName(OMPC_map)
21680 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21681 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21682 continue;
21683 }
21684 }
21685 }
21686
21687 // Try to find the associated user-defined mapper.
21689 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21690 Type.getCanonicalType(), UnresolvedMapper);
21691 if (ER.isInvalid())
21692 continue;
21693 MVLI.UDMapperList.push_back(ER.get());
21694
21695 // Save the current expression.
21696 MVLI.ProcessedVarList.push_back(RE);
21697
21698 // Store the components in the stack so that they can be used to check
21699 // against other clauses later on.
21700 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21701 /*WhereFoundClauseKind=*/OMPC_map);
21702
21703 // Save the components and declaration to create the clause. For purposes of
21704 // the clause creation, any component list that has has base 'this' uses
21705 // null as base declaration.
21706 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21707 MVLI.VarComponents.back().append(CurComponents.begin(),
21708 CurComponents.end());
21709 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21710 : CurDeclaration);
21711 }
21712}
21713
21715 ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21716 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21717 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21718 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21719 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21720 const OMPVarListLocTy &Locs, bool NoDiagnose,
21721 ArrayRef<Expr *> UnresolvedMappers) {
21722 OpenMPMapModifierKind Modifiers[] = {
21727
21728 // Process map-type-modifiers, flag errors for duplicate modifiers.
21729 unsigned Count = 0;
21730 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21731 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21732 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21733 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21734 continue;
21735 }
21736 assert(Count < NumberOfOMPMapClauseModifiers &&
21737 "Modifiers exceed the allowed number of map type modifiers");
21738 Modifiers[Count] = MapTypeModifiers[I];
21739 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21740 ++Count;
21741 }
21742
21743 MappableVarListInfo MVLI(VarList);
21744 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
21745 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21746 MapType, Modifiers, IsMapTypeImplicit,
21747 NoDiagnose);
21748
21749 // We need to produce a map clause even if we don't have variables so that
21750 // other diagnostics related with non-existing map clauses are accurate.
21751 return OMPMapClause::Create(Context, Locs, MVLI.ProcessedVarList,
21752 MVLI.VarBaseDeclarations, MVLI.VarComponents,
21753 MVLI.UDMapperList, Modifiers, ModifiersLoc,
21754 MapperIdScopeSpec.getWithLocInContext(Context),
21755 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21756}
21757
21760 assert(ParsedType.isUsable());
21761
21762 QualType ReductionType = GetTypeFromParser(ParsedType.get());
21763 if (ReductionType.isNull())
21764 return QualType();
21765
21766 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21767 // A type name in a declare reduction directive cannot be a function type, an
21768 // array type, a reference type, or a type qualified with const, volatile or
21769 // restrict.
21770 if (ReductionType.hasQualifiers()) {
21771 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21772 return QualType();
21773 }
21774
21775 if (ReductionType->isFunctionType()) {
21776 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21777 return QualType();
21778 }
21779 if (ReductionType->isReferenceType()) {
21780 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21781 return QualType();
21782 }
21783 if (ReductionType->isArrayType()) {
21784 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21785 return QualType();
21786 }
21787 return ReductionType;
21788}
21789
21791 Scope *S, DeclContext *DC, DeclarationName Name,
21792 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21793 AccessSpecifier AS, Decl *PrevDeclInScope) {
21795 Decls.reserve(ReductionTypes.size());
21796
21797 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
21799 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21800 // A reduction-identifier may not be re-declared in the current scope for the
21801 // same type or for a type that is compatible according to the base language
21802 // rules.
21803 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21804 OMPDeclareReductionDecl *PrevDRD = nullptr;
21805 bool InCompoundScope = true;
21806 if (S != nullptr) {
21807 // Find previous declaration with the same name not referenced in other
21808 // declarations.
21810 InCompoundScope =
21811 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21812 LookupName(Lookup, S);
21813 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21814 /*AllowInlineNamespace=*/false);
21815 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21816 LookupResult::Filter Filter = Lookup.makeFilter();
21817 while (Filter.hasNext()) {
21818 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21819 if (InCompoundScope) {
21820 auto I = UsedAsPrevious.find(PrevDecl);
21821 if (I == UsedAsPrevious.end())
21822 UsedAsPrevious[PrevDecl] = false;
21823 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21824 UsedAsPrevious[D] = true;
21825 }
21826 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21827 PrevDecl->getLocation();
21828 }
21829 Filter.done();
21830 if (InCompoundScope) {
21831 for (const auto &PrevData : UsedAsPrevious) {
21832 if (!PrevData.second) {
21833 PrevDRD = PrevData.first;
21834 break;
21835 }
21836 }
21837 }
21838 } else if (PrevDeclInScope != nullptr) {
21839 auto *PrevDRDInScope = PrevDRD =
21840 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21841 do {
21842 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21843 PrevDRDInScope->getLocation();
21844 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21845 } while (PrevDRDInScope != nullptr);
21846 }
21847 for (const auto &TyData : ReductionTypes) {
21848 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21849 bool Invalid = false;
21850 if (I != PreviousRedeclTypes.end()) {
21851 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21852 << TyData.first;
21853 Diag(I->second, diag::note_previous_definition);
21854 Invalid = true;
21855 }
21856 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21857 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
21858 Name, TyData.first, PrevDRD);
21859 DC->addDecl(DRD);
21860 DRD->setAccess(AS);
21861 Decls.push_back(DRD);
21862 if (Invalid)
21863 DRD->setInvalidDecl();
21864 else
21865 PrevDRD = DRD;
21866 }
21867
21868 return DeclGroupPtrTy::make(
21869 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
21870}
21871
21873 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21874
21875 // Enter new function scope.
21879
21880 if (S != nullptr)
21881 PushDeclContext(S, DRD);
21882 else
21883 CurContext = DRD;
21884
21887
21888 QualType ReductionType = DRD->getType();
21889 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21890 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21891 // uses semantics of argument handles by value, but it should be passed by
21892 // reference. C lang does not support references, so pass all parameters as
21893 // pointers.
21894 // Create 'T omp_in;' variable.
21895 VarDecl *OmpInParm =
21896 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
21897 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21898 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21899 // uses semantics of argument handles by value, but it should be passed by
21900 // reference. C lang does not support references, so pass all parameters as
21901 // pointers.
21902 // Create 'T omp_out;' variable.
21903 VarDecl *OmpOutParm =
21904 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
21905 if (S != nullptr) {
21906 PushOnScopeChains(OmpInParm, S);
21907 PushOnScopeChains(OmpOutParm, S);
21908 } else {
21909 DRD->addDecl(OmpInParm);
21910 DRD->addDecl(OmpOutParm);
21911 }
21912 Expr *InE =
21913 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
21914 Expr *OutE =
21915 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
21916 DRD->setCombinerData(InE, OutE);
21917}
21918
21920 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21923
21926
21927 if (Combiner != nullptr)
21928 DRD->setCombiner(Combiner);
21929 else
21930 DRD->setInvalidDecl();
21931}
21932
21934 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21935
21936 // Enter new function scope.
21939
21940 if (S != nullptr)
21941 PushDeclContext(S, DRD);
21942 else
21943 CurContext = DRD;
21944
21947
21948 QualType ReductionType = DRD->getType();
21949 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21950 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21951 // uses semantics of argument handles by value, but it should be passed by
21952 // reference. C lang does not support references, so pass all parameters as
21953 // pointers.
21954 // Create 'T omp_priv;' variable.
21955 VarDecl *OmpPrivParm =
21956 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
21957 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21958 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21959 // uses semantics of argument handles by value, but it should be passed by
21960 // reference. C lang does not support references, so pass all parameters as
21961 // pointers.
21962 // Create 'T omp_orig;' variable.
21963 VarDecl *OmpOrigParm =
21964 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
21965 if (S != nullptr) {
21966 PushOnScopeChains(OmpPrivParm, S);
21967 PushOnScopeChains(OmpOrigParm, S);
21968 } else {
21969 DRD->addDecl(OmpPrivParm);
21970 DRD->addDecl(OmpOrigParm);
21971 }
21972 Expr *OrigE =
21973 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
21974 Expr *PrivE =
21975 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
21976 DRD->setInitializerData(OrigE, PrivE);
21977 return OmpPrivParm;
21978}
21979
21981 VarDecl *OmpPrivParm) {
21982 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21985
21988
21989 if (Initializer != nullptr) {
21990 DRD->setInitializer(Initializer, OMPDeclareReductionDecl::CallInit);
21991 } else if (OmpPrivParm->hasInit()) {
21992 DRD->setInitializer(OmpPrivParm->getInit(),
21993 OmpPrivParm->isDirectInit()
21996 } else {
21997 DRD->setInvalidDecl();
21998 }
21999}
22000
22002 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22003 for (Decl *D : DeclReductions.get()) {
22004 if (IsValid) {
22005 if (S)
22006 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22007 /*AddToContext=*/false);
22008 } else {
22009 D->setInvalidDecl();
22010 }
22011 }
22012 return DeclReductions;
22013}
22014
22016 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
22017 QualType T = TInfo->getType();
22018 if (D.isInvalidType())
22019 return true;
22020
22021 if (getLangOpts().CPlusPlus) {
22022 // Check that there are no default arguments (C++ only).
22024 }
22025
22026 return CreateParsedType(T, TInfo);
22027}
22028
22031 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22032
22033 QualType MapperType = GetTypeFromParser(ParsedType.get());
22034 assert(!MapperType.isNull() && "Expect valid mapper type");
22035
22036 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22037 // The type must be of struct, union or class type in C and C++
22038 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22039 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22040 return QualType();
22041 }
22042 return MapperType;
22043}
22044
22046 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22048 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22049 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22051 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22052 // A mapper-identifier may not be redeclared in the current scope for the
22053 // same type or for a type that is compatible according to the base language
22054 // rules.
22055 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22056 OMPDeclareMapperDecl *PrevDMD = nullptr;
22057 bool InCompoundScope = true;
22058 if (S != nullptr) {
22059 // Find previous declaration with the same name not referenced in other
22060 // declarations.
22062 InCompoundScope =
22063 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22064 LookupName(Lookup, S);
22065 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22066 /*AllowInlineNamespace=*/false);
22067 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22068 LookupResult::Filter Filter = Lookup.makeFilter();
22069 while (Filter.hasNext()) {
22070 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22071 if (InCompoundScope) {
22072 auto I = UsedAsPrevious.find(PrevDecl);
22073 if (I == UsedAsPrevious.end())
22074 UsedAsPrevious[PrevDecl] = false;
22075 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22076 UsedAsPrevious[D] = true;
22077 }
22078 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22079 PrevDecl->getLocation();
22080 }
22081 Filter.done();
22082 if (InCompoundScope) {
22083 for (const auto &PrevData : UsedAsPrevious) {
22084 if (!PrevData.second) {
22085 PrevDMD = PrevData.first;
22086 break;
22087 }
22088 }
22089 }
22090 } else if (PrevDeclInScope) {
22091 auto *PrevDMDInScope = PrevDMD =
22092 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22093 do {
22094 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22095 PrevDMDInScope->getLocation();
22096 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22097 } while (PrevDMDInScope != nullptr);
22098 }
22099 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22100 bool Invalid = false;
22101 if (I != PreviousRedeclTypes.end()) {
22102 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22103 << MapperType << Name;
22104 Diag(I->second, diag::note_previous_definition);
22105 Invalid = true;
22106 }
22107 // Build expressions for implicit maps of data members with 'default'
22108 // mappers.
22109 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22110 Clauses.end());
22111 if (LangOpts.OpenMP >= 50)
22112 processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
22113 auto *DMD =
22114 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22115 ClausesWithImplicit, PrevDMD);
22116 if (S)
22117 PushOnScopeChains(DMD, S);
22118 else
22119 DC->addDecl(DMD);
22120 DMD->setAccess(AS);
22121 if (Invalid)
22122 DMD->setInvalidDecl();
22123
22124 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22125 VD->setDeclContext(DMD);
22126 VD->setLexicalDeclContext(DMD);
22127 DMD->addDecl(VD);
22128 DMD->setMapperVarRef(MapperVarRef);
22129
22131}
22132
22135 SourceLocation StartLoc,
22136 DeclarationName VN) {
22137 TypeSourceInfo *TInfo =
22138 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22140 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22141 MapperType, TInfo, SC_None);
22142 if (S)
22143 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22144 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22145 DSAStack->addDeclareMapperVarRef(E);
22146 return E;
22147}
22148
22150 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22151 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22152 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22153 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22154 return true;
22156 return true;
22157 return false;
22158 }
22159 return true;
22160}
22161
22163 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22164 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22165}
22166
22168 SourceLocation StartLoc,
22169 SourceLocation LParenLoc,
22170 SourceLocation EndLoc) {
22171 Expr *ValExpr = NumTeams;
22172 Stmt *HelperValStmt = nullptr;
22173
22174 // OpenMP [teams Constrcut, Restrictions]
22175 // The num_teams expression must evaluate to a positive integer value.
22176 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22177 /*StrictlyPositive=*/true))
22178 return nullptr;
22179
22180 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22181 OpenMPDirectiveKind CaptureRegion =
22182 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22183 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22184 ValExpr = MakeFullExpr(ValExpr).get();
22185 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22186 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22187 HelperValStmt = buildPreInits(Context, Captures);
22188 }
22189
22190 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22191 StartLoc, LParenLoc, EndLoc);
22192}
22193
22195 SourceLocation StartLoc,
22196 SourceLocation LParenLoc,
22197 SourceLocation EndLoc) {
22198 Expr *ValExpr = ThreadLimit;
22199 Stmt *HelperValStmt = nullptr;
22200
22201 // OpenMP [teams Constrcut, Restrictions]
22202 // The thread_limit expression must evaluate to a positive integer value.
22203 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22204 /*StrictlyPositive=*/true))
22205 return nullptr;
22206
22207 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22209 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22210 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22211 ValExpr = MakeFullExpr(ValExpr).get();
22212 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22213 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22214 HelperValStmt = buildPreInits(Context, Captures);
22215 }
22216
22217 return new (Context) OMPThreadLimitClause(
22218 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22219}
22220
22222 SourceLocation StartLoc,
22223 SourceLocation LParenLoc,
22224 SourceLocation EndLoc) {
22225 Expr *ValExpr = Priority;
22226 Stmt *HelperValStmt = nullptr;
22227 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22228
22229 // OpenMP [2.9.1, task Constrcut]
22230 // The priority-value is a non-negative numerical scalar expression.
22232 ValExpr, *this, OMPC_priority,
22233 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22234 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22235 return nullptr;
22236
22237 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22238 StartLoc, LParenLoc, EndLoc);
22239}
22240
22242 SourceLocation StartLoc,
22243 SourceLocation LParenLoc,
22244 SourceLocation EndLoc) {
22245 Expr *ValExpr = Grainsize;
22246 Stmt *HelperValStmt = nullptr;
22247 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22248
22249 // OpenMP [2.9.2, taskloop Constrcut]
22250 // The parameter of the grainsize clause must be a positive integer
22251 // expression.
22253 ValExpr, *this, OMPC_grainsize,
22254 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22255 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22256 return nullptr;
22257
22258 return new (Context) OMPGrainsizeClause(ValExpr, HelperValStmt, CaptureRegion,
22259 StartLoc, LParenLoc, EndLoc);
22260}
22261
22263 SourceLocation StartLoc,
22264 SourceLocation LParenLoc,
22265 SourceLocation EndLoc) {
22266 Expr *ValExpr = NumTasks;
22267 Stmt *HelperValStmt = nullptr;
22268 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22269
22270 // OpenMP [2.9.2, taskloop Constrcut]
22271 // The parameter of the num_tasks clause must be a positive integer
22272 // expression.
22274 ValExpr, *this, OMPC_num_tasks,
22275 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22276 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22277 return nullptr;
22278
22279 return new (Context) OMPNumTasksClause(ValExpr, HelperValStmt, CaptureRegion,
22280 StartLoc, LParenLoc, EndLoc);
22281}
22282
22284 SourceLocation LParenLoc,
22285 SourceLocation EndLoc) {
22286 // OpenMP [2.13.2, critical construct, Description]
22287 // ... where hint-expression is an integer constant expression that evaluates
22288 // to a valid lock hint.
22289 ExprResult HintExpr =
22290 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22291 if (HintExpr.isInvalid())
22292 return nullptr;
22293 return new (Context)
22294 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22295}
22296
22297/// Tries to find omp_event_handle_t type.
22299 DSAStackTy *Stack) {
22300 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22301 if (!OMPEventHandleT.isNull())
22302 return true;
22303 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22304 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22305 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22306 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22307 return false;
22308 }
22309 Stack->setOMPEventHandleT(PT.get());
22310 return true;
22311}
22312
22314 SourceLocation LParenLoc,
22315 SourceLocation EndLoc) {
22316 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22317 !Evt->isInstantiationDependent() &&
22319 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
22320 return nullptr;
22321 // OpenMP 5.0, 2.10.1 task Construct.
22322 // event-handle is a variable of the omp_event_handle_t type.
22323 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22324 if (!Ref) {
22325 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22326 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22327 return nullptr;
22328 }
22329 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22330 if (!VD) {
22331 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22332 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22333 return nullptr;
22334 }
22335 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22336 VD->getType()) ||
22337 VD->getType().isConstant(Context)) {
22338 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22339 << "omp_event_handle_t" << 1 << VD->getType()
22340 << Evt->getSourceRange();
22341 return nullptr;
22342 }
22343 // OpenMP 5.0, 2.10.1 task Construct
22344 // [detach clause]... The event-handle will be considered as if it was
22345 // specified on a firstprivate clause.
22346 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22347 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22348 DVar.RefExpr) {
22349 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22350 << getOpenMPClauseName(DVar.CKind)
22351 << getOpenMPClauseName(OMPC_firstprivate);
22352 reportOriginalDsa(*this, DSAStack, VD, DVar);
22353 return nullptr;
22354 }
22355 }
22356
22357 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22358}
22359
22361 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22362 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22363 SourceLocation EndLoc) {
22364 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22365 std::string Values;
22366 Values += "'";
22367 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22368 Values += "'";
22369 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22370 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22371 return nullptr;
22372 }
22373 Expr *ValExpr = ChunkSize;
22374 Stmt *HelperValStmt = nullptr;
22375 if (ChunkSize) {
22376 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22377 !ChunkSize->isInstantiationDependent() &&
22378 !ChunkSize->containsUnexpandedParameterPack()) {
22379 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22380 ExprResult Val =
22381 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22382 if (Val.isInvalid())
22383 return nullptr;
22384
22385 ValExpr = Val.get();
22386
22387 // OpenMP [2.7.1, Restrictions]
22388 // chunk_size must be a loop invariant integer expression with a positive
22389 // value.
22391 ValExpr->getIntegerConstantExpr(Context)) {
22392 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22393 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22394 << "dist_schedule" << ChunkSize->getSourceRange();
22395 return nullptr;
22396 }
22398 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22399 LangOpts.OpenMP) != OMPD_unknown &&
22401 ValExpr = MakeFullExpr(ValExpr).get();
22402 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22403 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22404 HelperValStmt = buildPreInits(Context, Captures);
22405 }
22406 }
22407 }
22408
22409 return new (Context)
22410 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22411 Kind, ValExpr, HelperValStmt);
22412}
22413
22416 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22417 SourceLocation KindLoc, SourceLocation EndLoc) {
22418 if (getLangOpts().OpenMP < 50) {
22419 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22420 Kind != OMPC_DEFAULTMAP_scalar) {
22421 std::string Value;
22422 SourceLocation Loc;
22423 Value += "'";
22424 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22425 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22426 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22427 Loc = MLoc;
22428 } else {
22429 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22430 OMPC_DEFAULTMAP_scalar);
22431 Loc = KindLoc;
22432 }
22433 Value += "'";
22434 Diag(Loc, diag::err_omp_unexpected_clause_value)
22435 << Value << getOpenMPClauseName(OMPC_defaultmap);
22436 return nullptr;
22437 }
22438 } else {
22439 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22440 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22441 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
22442 if (!isDefaultmapKind || !isDefaultmapModifier) {
22443 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
22444 if (LangOpts.OpenMP == 50) {
22445 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22446 "'firstprivate', 'none', 'default'";
22447 if (!isDefaultmapKind && isDefaultmapModifier) {
22448 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22449 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22450 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22451 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22452 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22453 } else {
22454 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22455 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22456 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22457 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22458 }
22459 } else {
22460 StringRef ModifierValue =
22461 "'alloc', 'from', 'to', 'tofrom', "
22462 "'firstprivate', 'none', 'default', 'present'";
22463 if (!isDefaultmapKind && isDefaultmapModifier) {
22464 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22465 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22466 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22467 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22468 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22469 } else {
22470 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22471 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22472 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22473 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22474 }
22475 }
22476 return nullptr;
22477 }
22478
22479 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22480 // At most one defaultmap clause for each category can appear on the
22481 // directive.
22482 if (DSAStack->checkDefaultmapCategory(Kind)) {
22483 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22484 return nullptr;
22485 }
22486 }
22487 if (Kind == OMPC_DEFAULTMAP_unknown) {
22488 // Variable category is not specified - mark all categories.
22489 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22490 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22491 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22492 } else {
22493 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22494 }
22495
22496 return new (Context)
22497 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22498}
22499
22501 DeclareTargetContextInfo &DTCI) {
22502 DeclContext *CurLexicalContext = getCurLexicalContext();
22503 if (!CurLexicalContext->isFileContext() &&
22504 !CurLexicalContext->isExternCContext() &&
22505 !CurLexicalContext->isExternCXXContext() &&
22506 !isa<CXXRecordDecl>(CurLexicalContext) &&
22507 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22508 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22509 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22510 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22511 return false;
22512 }
22513 DeclareTargetNesting.push_back(DTCI);
22514 return true;
22515}
22516
22517const Sema::DeclareTargetContextInfo
22519 assert(!DeclareTargetNesting.empty() &&
22520 "check isInOpenMPDeclareTargetContext() first!");
22521 return DeclareTargetNesting.pop_back_val();
22522}
22523
22525 DeclareTargetContextInfo &DTCI) {
22526 for (auto &It : DTCI.ExplicitlyMapped)
22527 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22528}
22529
22531 if (DeclareTargetNesting.empty())
22532 return;
22533 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22534 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22535 << getOpenMPDirectiveName(DTCI.Kind);
22536}
22537
22539 CXXScopeSpec &ScopeSpec,
22540 const DeclarationNameInfo &Id) {
22541 LookupResult Lookup(*this, Id, LookupOrdinaryName);
22542 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
22543
22544 if (Lookup.isAmbiguous())
22545 return nullptr;
22546 Lookup.suppressDiagnostics();
22547
22548 if (!Lookup.isSingleResult()) {
22549 VarOrFuncDeclFilterCCC CCC(*this);
22550 if (TypoCorrection Corrected =
22551 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
22553 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
22554 << Id.getName());
22555 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22556 return nullptr;
22557 }
22558
22559 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22560 return nullptr;
22561 }
22562
22563 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22564 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22565 !isa<FunctionTemplateDecl>(ND)) {
22566 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22567 return nullptr;
22568 }
22569 return ND;
22570}
22571
22573 OMPDeclareTargetDeclAttr::MapTypeTy MT,
22574 DeclareTargetContextInfo &DTCI) {
22575 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22576 isa<FunctionTemplateDecl>(ND)) &&
22577 "Expected variable, function or function template.");
22578
22579 // Diagnose marking after use as it may lead to incorrect diagnosis and
22580 // codegen.
22581 if (LangOpts.OpenMP >= 50 &&
22582 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22583 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22584
22585 // Explicit declare target lists have precedence.
22586 const unsigned Level = -1;
22587
22588 auto *VD = cast<ValueDecl>(ND);
22590 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22591 if (ActiveAttr && ActiveAttr.value()->getDevType() != DTCI.DT &&
22592 ActiveAttr.value()->getLevel() == Level) {
22593 Diag(Loc, diag::err_omp_device_type_mismatch)
22594 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22595 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22596 ActiveAttr.value()->getDevType());
22597 return;
22598 }
22599 if (ActiveAttr && ActiveAttr.value()->getMapType() != MT &&
22600 ActiveAttr.value()->getLevel() == Level) {
22601 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22602 return;
22603 }
22604
22605 if (ActiveAttr && ActiveAttr.value()->getLevel() == Level)
22606 return;
22607
22608 Expr *IndirectE = nullptr;
22609 bool IsIndirect = false;
22610 if (DTCI.Indirect) {
22611 IndirectE = DTCI.Indirect.value();
22612 if (!IndirectE)
22613 IsIndirect = true;
22614 }
22615 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22616 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
22617 SourceRange(Loc, Loc));
22618 ND->addAttr(A);
22620 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22621 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
22622}
22623
22625 Sema &SemaRef, Decl *D) {
22626 if (!D || !isa<VarDecl>(D))
22627 return;
22628 auto *VD = cast<VarDecl>(D);
22630 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22631 if (SemaRef.LangOpts.OpenMP >= 50 &&
22632 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22633 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22634 VD->hasGlobalStorage()) {
22635 if (!MapTy || *MapTy != OMPDeclareTargetDeclAttr::MT_To) {
22636 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22637 // If a lambda declaration and definition appears between a
22638 // declare target directive and the matching end declare target
22639 // directive, all variables that are captured by the lambda
22640 // expression must also appear in a to clause.
22641 SemaRef.Diag(VD->getLocation(),
22642 diag::err_omp_lambda_capture_in_declare_target_not_to);
22643 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22644 << VD << 0 << SR;
22645 return;
22646 }
22647 }
22648 if (MapTy)
22649 return;
22650 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22651 SemaRef.Diag(SL, diag::note_used_here) << SR;
22652}
22653
22655 Sema &SemaRef, DSAStackTy *Stack,
22656 ValueDecl *VD) {
22657 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22658 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22659 /*FullCheck=*/false);
22660}
22661
22663 SourceLocation IdLoc) {
22664 if (!D || D->isInvalidDecl())
22665 return;
22666 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
22667 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22668 if (auto *VD = dyn_cast<VarDecl>(D)) {
22669 // Only global variables can be marked as declare target.
22670 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22671 !VD->isStaticDataMember())
22672 return;
22673 // 2.10.6: threadprivate variable cannot appear in a declare target
22674 // directive.
22675 if (DSAStack->isThreadPrivate(VD)) {
22676 Diag(SL, diag::err_omp_threadprivate_in_target);
22677 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22678 return;
22679 }
22680 }
22681 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22682 D = FTD->getTemplatedDecl();
22683 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22685 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22686 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22687 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22688 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22689 return;
22690 }
22691 }
22692 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22693 // Problem if any with var declared with incomplete type will be reported
22694 // as normal, so no need to check it here.
22695 if ((E || !VD->getType()->isIncompleteType()) &&
22696 !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
22697 return;
22698 if (!E && isInOpenMPDeclareTargetContext()) {
22699 // Checking declaration inside declare target region.
22700 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22701 isa<FunctionTemplateDecl>(D)) {
22703 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22704 unsigned Level = DeclareTargetNesting.size();
22705 if (ActiveAttr && ActiveAttr.value()->getLevel() >= Level)
22706 return;
22707 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22708 Expr *IndirectE = nullptr;
22709 bool IsIndirect = false;
22710 if (DTCI.Indirect) {
22711 IndirectE = DTCI.Indirect.value();
22712 if (!IndirectE)
22713 IsIndirect = true;
22714 }
22715 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22716 Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, IndirectE,
22717 IsIndirect, Level, SourceRange(DTCI.Loc, DTCI.Loc));
22718 D->addAttr(A);
22720 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22721 }
22722 return;
22723 }
22724 }
22725 if (!E)
22726 return;
22728}
22729
22731 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22732 ArrayRef<SourceLocation> MotionModifiersLoc,
22733 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22734 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22735 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22739
22740 // Process motion-modifiers, flag errors for duplicate modifiers.
22741 unsigned Count = 0;
22742 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22743 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22744 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22745 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22746 continue;
22747 }
22748 assert(Count < NumberOfOMPMotionModifiers &&
22749 "Modifiers exceed the allowed number of motion modifiers");
22750 Modifiers[Count] = MotionModifiers[I];
22751 ModifiersLoc[Count] = MotionModifiersLoc[I];
22752 ++Count;
22753 }
22754
22755 MappableVarListInfo MVLI(VarList);
22756 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
22757 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22758 if (MVLI.ProcessedVarList.empty())
22759 return nullptr;
22760
22761 return OMPToClause::Create(
22762 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22763 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22764 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
22765}
22766
22768 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22769 ArrayRef<SourceLocation> MotionModifiersLoc,
22770 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22771 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22772 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22776
22777 // Process motion-modifiers, flag errors for duplicate modifiers.
22778 unsigned Count = 0;
22779 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22780 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22781 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22782 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22783 continue;
22784 }
22785 assert(Count < NumberOfOMPMotionModifiers &&
22786 "Modifiers exceed the allowed number of motion modifiers");
22787 Modifiers[Count] = MotionModifiers[I];
22788 ModifiersLoc[Count] = MotionModifiersLoc[I];
22789 ++Count;
22790 }
22791
22792 MappableVarListInfo MVLI(VarList);
22793 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22794 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22795 if (MVLI.ProcessedVarList.empty())
22796 return nullptr;
22797
22798 return OMPFromClause::Create(
22799 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22800 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22801 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
22802}
22803
22805 const OMPVarListLocTy &Locs) {
22806 MappableVarListInfo MVLI(VarList);
22807 SmallVector<Expr *, 8> PrivateCopies;
22809
22810 for (Expr *RefExpr : VarList) {
22811 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22812 SourceLocation ELoc;
22813 SourceRange ERange;
22814 Expr *SimpleRefExpr = RefExpr;
22815 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
22816 if (Res.second) {
22817 // It will be analyzed later.
22818 MVLI.ProcessedVarList.push_back(RefExpr);
22819 PrivateCopies.push_back(nullptr);
22820 Inits.push_back(nullptr);
22821 }
22822 ValueDecl *D = Res.first;
22823 if (!D)
22824 continue;
22825
22826 QualType Type = D->getType();
22827 Type = Type.getNonReferenceType().getUnqualifiedType();
22828
22829 auto *VD = dyn_cast<VarDecl>(D);
22830
22831 // Item should be a pointer or reference to pointer.
22832 if (!Type->isPointerType()) {
22833 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22834 << 0 << RefExpr->getSourceRange();
22835 continue;
22836 }
22837
22838 // Build the private variable and the expression that refers to it.
22839 auto VDPrivate =
22840 buildVarDecl(*this, ELoc, Type, D->getName(),
22841 D->hasAttrs() ? &D->getAttrs() : nullptr,
22842 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22843 if (VDPrivate->isInvalidDecl())
22844 continue;
22845
22846 CurContext->addDecl(VDPrivate);
22847 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22848 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22849
22850 // Add temporary variable to initialize the private copy of the pointer.
22851 VarDecl *VDInit =
22852 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
22853 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22854 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22855 AddInitializerToDecl(VDPrivate,
22856 DefaultLvalueConversion(VDInitRefExpr).get(),
22857 /*DirectInit=*/false);
22858
22859 // If required, build a capture to implement the privatization initialized
22860 // with the current list item value.
22861 DeclRefExpr *Ref = nullptr;
22862 if (!VD)
22863 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
22864 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22865 PrivateCopies.push_back(VDPrivateRefExpr);
22866 Inits.push_back(VDInitRefExpr);
22867
22868 // We need to add a data sharing attribute for this variable to make sure it
22869 // is correctly captured. A variable that shows up in a use_device_ptr has
22870 // similar properties of a first private variable.
22871 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22872
22873 // Create a mappable component for the list item. List items in this clause
22874 // only need a component.
22875 MVLI.VarBaseDeclarations.push_back(D);
22876 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22877 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22878 /*IsNonContiguous=*/false);
22879 }
22880
22881 if (MVLI.ProcessedVarList.empty())
22882 return nullptr;
22883
22885 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22886 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22887}
22888
22890 const OMPVarListLocTy &Locs) {
22891 MappableVarListInfo MVLI(VarList);
22892
22893 for (Expr *RefExpr : VarList) {
22894 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22895 SourceLocation ELoc;
22896 SourceRange ERange;
22897 Expr *SimpleRefExpr = RefExpr;
22898 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
22899 /*AllowArraySection=*/true);
22900 if (Res.second) {
22901 // It will be analyzed later.
22902 MVLI.ProcessedVarList.push_back(RefExpr);
22903 }
22904 ValueDecl *D = Res.first;
22905 if (!D)
22906 continue;
22907 auto *VD = dyn_cast<VarDecl>(D);
22908
22909 // If required, build a capture to implement the privatization initialized
22910 // with the current list item value.
22911 DeclRefExpr *Ref = nullptr;
22912 if (!VD)
22913 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
22914 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22915
22916 // We need to add a data sharing attribute for this variable to make sure it
22917 // is correctly captured. A variable that shows up in a use_device_addr has
22918 // similar properties of a first private variable.
22919 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22920
22921 // Create a mappable component for the list item. List items in this clause
22922 // only need a component.
22923 MVLI.VarBaseDeclarations.push_back(D);
22924 MVLI.VarComponents.emplace_back();
22925 Expr *Component = SimpleRefExpr;
22926 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22927 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22928 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
22929 MVLI.VarComponents.back().emplace_back(Component, D,
22930 /*IsNonContiguous=*/false);
22931 }
22932
22933 if (MVLI.ProcessedVarList.empty())
22934 return nullptr;
22935
22936 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
22937 MVLI.VarBaseDeclarations,
22938 MVLI.VarComponents);
22939}
22940
22942 const OMPVarListLocTy &Locs) {
22943 MappableVarListInfo MVLI(VarList);
22944 for (Expr *RefExpr : VarList) {
22945 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
22946 SourceLocation ELoc;
22947 SourceRange ERange;
22948 Expr *SimpleRefExpr = RefExpr;
22949 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
22950 if (Res.second) {
22951 // It will be analyzed later.
22952 MVLI.ProcessedVarList.push_back(RefExpr);
22953 }
22954 ValueDecl *D = Res.first;
22955 if (!D)
22956 continue;
22957
22958 QualType Type = D->getType();
22959 // item should be a pointer or array or reference to pointer or array
22960 if (!Type.getNonReferenceType()->isPointerType() &&
22961 !Type.getNonReferenceType()->isArrayType()) {
22962 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22963 << 0 << RefExpr->getSourceRange();
22964 continue;
22965 }
22966
22967 // Check if the declaration in the clause does not show up in any data
22968 // sharing attribute.
22969 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22970 if (isOpenMPPrivate(DVar.CKind)) {
22971 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22972 << getOpenMPClauseName(DVar.CKind)
22973 << getOpenMPClauseName(OMPC_is_device_ptr)
22974 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22975 reportOriginalDsa(*this, DSAStack, D, DVar);
22976 continue;
22977 }
22978
22979 const Expr *ConflictExpr;
22980 if (DSAStack->checkMappableExprComponentListsForDecl(
22981 D, /*CurrentRegionOnly=*/true,
22982 [&ConflictExpr](
22984 OpenMPClauseKind) -> bool {
22985 ConflictExpr = R.front().getAssociatedExpression();
22986 return true;
22987 })) {
22988 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22989 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22990 << ConflictExpr->getSourceRange();
22991 continue;
22992 }
22993
22994 // Store the components in the stack so that they can be used to check
22995 // against other clauses later on.
22997 SimpleRefExpr, D, /*IsNonContiguous=*/false);
22998 DSAStack->addMappableExpressionComponents(
22999 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23000
23001 // Record the expression we've just processed.
23002 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23003
23004 // Create a mappable component for the list item. List items in this clause
23005 // only need a component. We use a null declaration to signal fields in
23006 // 'this'.
23007 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23008 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23009 "Unexpected device pointer expression!");
23010 MVLI.VarBaseDeclarations.push_back(
23011 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23012 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23013 MVLI.VarComponents.back().push_back(MC);
23014 }
23015
23016 if (MVLI.ProcessedVarList.empty())
23017 return nullptr;
23018
23019 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23020 MVLI.VarBaseDeclarations,
23021 MVLI.VarComponents);
23022}
23023
23025 const OMPVarListLocTy &Locs) {
23026 MappableVarListInfo MVLI(VarList);
23027 for (Expr *RefExpr : VarList) {
23028 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23029 SourceLocation ELoc;
23030 SourceRange ERange;
23031 Expr *SimpleRefExpr = RefExpr;
23032 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23033 /*AllowArraySection=*/true);
23034 if (Res.second) {
23035 // It will be analyzed later.
23036 MVLI.ProcessedVarList.push_back(RefExpr);
23037 }
23038 ValueDecl *D = Res.first;
23039 if (!D)
23040 continue;
23041
23042 // Check if the declaration in the clause does not show up in any data
23043 // sharing attribute.
23044 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23045 if (isOpenMPPrivate(DVar.CKind)) {
23046 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23047 << getOpenMPClauseName(DVar.CKind)
23048 << getOpenMPClauseName(OMPC_has_device_addr)
23049 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23050 reportOriginalDsa(*this, DSAStack, D, DVar);
23051 continue;
23052 }
23053
23054 const Expr *ConflictExpr;
23055 if (DSAStack->checkMappableExprComponentListsForDecl(
23056 D, /*CurrentRegionOnly=*/true,
23057 [&ConflictExpr](
23059 OpenMPClauseKind) -> bool {
23060 ConflictExpr = R.front().getAssociatedExpression();
23061 return true;
23062 })) {
23063 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23064 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23065 << ConflictExpr->getSourceRange();
23066 continue;
23067 }
23068
23069 // Store the components in the stack so that they can be used to check
23070 // against other clauses later on.
23072 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23073 DSAStack->addMappableExpressionComponents(
23074 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23075
23076 // Record the expression we've just processed.
23077 auto *VD = dyn_cast<VarDecl>(D);
23078 if (!VD && !CurContext->isDependentContext()) {
23079 DeclRefExpr *Ref =
23080 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23081 assert(Ref && "has_device_addr capture failed");
23082 MVLI.ProcessedVarList.push_back(Ref);
23083 } else
23084 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23085
23086 // Create a mappable component for the list item. List items in this clause
23087 // only need a component. We use a null declaration to signal fields in
23088 // 'this'.
23089 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23090 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23091 "Unexpected device pointer expression!");
23092 MVLI.VarBaseDeclarations.push_back(
23093 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23094 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23095 MVLI.VarComponents.back().push_back(MC);
23096 }
23097
23098 if (MVLI.ProcessedVarList.empty())
23099 return nullptr;
23100
23101 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23102 MVLI.VarBaseDeclarations,
23103 MVLI.VarComponents);
23104}
23105
23107 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23108 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23109 if (Allocator) {
23110 // OpenMP [2.11.4 allocate Clause, Description]
23111 // allocator is an expression of omp_allocator_handle_t type.
23112 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStack))
23113 return nullptr;
23114
23115 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23116 if (AllocatorRes.isInvalid())
23117 return nullptr;
23118 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23119 DSAStack->getOMPAllocatorHandleT(),
23121 /*AllowExplicit=*/true);
23122 if (AllocatorRes.isInvalid())
23123 return nullptr;
23124 Allocator = AllocatorRes.get();
23125 } else {
23126 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23127 // allocate clauses that appear on a target construct or on constructs in a
23128 // target region must specify an allocator expression unless a requires
23129 // directive with the dynamic_allocators clause is present in the same
23130 // compilation unit.
23131 if (LangOpts.OpenMPIsDevice &&
23132 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23133 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23134 }
23135 // Analyze and build list of variables.
23137 for (Expr *RefExpr : VarList) {
23138 assert(RefExpr && "NULL expr in OpenMP private clause.");
23139 SourceLocation ELoc;
23140 SourceRange ERange;
23141 Expr *SimpleRefExpr = RefExpr;
23142 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23143 if (Res.second) {
23144 // It will be analyzed later.
23145 Vars.push_back(RefExpr);
23146 }
23147 ValueDecl *D = Res.first;
23148 if (!D)
23149 continue;
23150
23151 auto *VD = dyn_cast<VarDecl>(D);
23152 DeclRefExpr *Ref = nullptr;
23153 if (!VD && !CurContext->isDependentContext())
23154 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
23155 Vars.push_back((VD || CurContext->isDependentContext())
23156 ? RefExpr->IgnoreParens()
23157 : Ref);
23158 }
23159
23160 if (Vars.empty())
23161 return nullptr;
23162
23163 if (Allocator)
23164 DSAStack->addInnerAllocatorExpr(Allocator);
23165 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
23166 ColonLoc, EndLoc, Vars);
23167}
23168
23170 SourceLocation StartLoc,
23171 SourceLocation LParenLoc,
23172 SourceLocation EndLoc) {
23174 for (Expr *RefExpr : VarList) {
23175 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23176 SourceLocation ELoc;
23177 SourceRange ERange;
23178 Expr *SimpleRefExpr = RefExpr;
23179 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23180 if (Res.second)
23181 // It will be analyzed later.
23182 Vars.push_back(RefExpr);
23183 ValueDecl *D = Res.first;
23184 if (!D)
23185 continue;
23186
23187 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23188 // A list-item cannot appear in more than one nontemporal clause.
23189 if (const Expr *PrevRef =
23190 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23191 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23192 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23193 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23194 << getOpenMPClauseName(OMPC_nontemporal);
23195 continue;
23196 }
23197
23198 Vars.push_back(RefExpr);
23199 }
23200
23201 if (Vars.empty())
23202 return nullptr;
23203
23204 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23205 Vars);
23206}
23207
23209 SourceLocation StartLoc,
23210 SourceLocation LParenLoc,
23211 SourceLocation EndLoc) {
23213 for (Expr *RefExpr : VarList) {
23214 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23215 SourceLocation ELoc;
23216 SourceRange ERange;
23217 Expr *SimpleRefExpr = RefExpr;
23218 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23219 /*AllowArraySection=*/true);
23220 if (Res.second)
23221 // It will be analyzed later.
23222 Vars.push_back(RefExpr);
23223 ValueDecl *D = Res.first;
23224 if (!D)
23225 continue;
23226
23227 const DSAStackTy::DSAVarData DVar =
23228 DSAStack->getTopDSA(D, /*FromParent=*/true);
23229 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23230 // A list item that appears in the inclusive or exclusive clause must appear
23231 // in a reduction clause with the inscan modifier on the enclosing
23232 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23233 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23234 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23235 << RefExpr->getSourceRange();
23236
23237 if (DSAStack->getParentDirective() != OMPD_unknown)
23238 DSAStack->markDeclAsUsedInScanDirective(D);
23239 Vars.push_back(RefExpr);
23240 }
23241
23242 if (Vars.empty())
23243 return nullptr;
23244
23245 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23246}
23247
23249 SourceLocation StartLoc,
23250 SourceLocation LParenLoc,
23251 SourceLocation EndLoc) {
23253 for (Expr *RefExpr : VarList) {
23254 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23255 SourceLocation ELoc;
23256 SourceRange ERange;
23257 Expr *SimpleRefExpr = RefExpr;
23258 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23259 /*AllowArraySection=*/true);
23260 if (Res.second)
23261 // It will be analyzed later.
23262 Vars.push_back(RefExpr);
23263 ValueDecl *D = Res.first;
23264 if (!D)
23265 continue;
23266
23267 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23268 DSAStackTy::DSAVarData DVar;
23269 if (ParentDirective != OMPD_unknown)
23270 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23271 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23272 // A list item that appears in the inclusive or exclusive clause must appear
23273 // in a reduction clause with the inscan modifier on the enclosing
23274 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23275 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23276 DVar.Modifier != OMPC_REDUCTION_inscan) {
23277 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23278 << RefExpr->getSourceRange();
23279 } else {
23280 DSAStack->markDeclAsUsedInScanDirective(D);
23281 }
23282 Vars.push_back(RefExpr);
23283 }
23284
23285 if (Vars.empty())
23286 return nullptr;
23287
23288 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23289}
23290
23291/// Tries to find omp_alloctrait_t type.
23292static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23293 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23294 if (!OMPAlloctraitT.isNull())
23295 return true;
23296 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23297 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23298 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23299 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23300 return false;
23301 }
23302 Stack->setOMPAlloctraitT(PT.get());
23303 return true;
23304}
23305
23307 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23309 // OpenMP [2.12.5, target Construct]
23310 // allocator is an identifier of omp_allocator_handle_t type.
23311 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
23312 return nullptr;
23313 // OpenMP [2.12.5, target Construct]
23314 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23315 if (llvm::any_of(
23316 Data,
23317 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23318 !findOMPAlloctraitT(*this, StartLoc, DSAStack))
23319 return nullptr;
23320 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23321 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23322 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23323 StringRef Allocator =
23324 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23325 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23326 PredefinedAllocators.insert(LookupSingleName(
23327 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23328 }
23329
23331 for (const UsesAllocatorsData &D : Data) {
23332 Expr *AllocatorExpr = nullptr;
23333 // Check allocator expression.
23334 if (D.Allocator->isTypeDependent()) {
23335 AllocatorExpr = D.Allocator;
23336 } else {
23337 // Traits were specified - need to assign new allocator to the specified
23338 // allocator, so it must be an lvalue.
23339 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23340 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23341 bool IsPredefinedAllocator = false;
23342 if (DRE)
23343 IsPredefinedAllocator = PredefinedAllocators.count(DRE->getDecl());
23344 if (!DRE ||
23346 AllocatorExpr->getType(), DSAStack->getOMPAllocatorHandleT()) ||
23347 Context.typesAreCompatible(AllocatorExpr->getType(),
23348 DSAStack->getOMPAllocatorHandleT(),
23349 /*CompareUnqualified=*/true)) ||
23350 (!IsPredefinedAllocator &&
23351 (AllocatorExpr->getType().isConstant(Context) ||
23352 !AllocatorExpr->isLValue()))) {
23353 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23354 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23355 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23356 continue;
23357 }
23358 // OpenMP [2.12.5, target Construct]
23359 // Predefined allocators appearing in a uses_allocators clause cannot have
23360 // traits specified.
23361 if (IsPredefinedAllocator && D.AllocatorTraits) {
23363 diag::err_omp_predefined_allocator_with_traits)
23365 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23366 << cast<NamedDecl>(DRE->getDecl())->getName()
23367 << D.Allocator->getSourceRange();
23368 continue;
23369 }
23370 // OpenMP [2.12.5, target Construct]
23371 // Non-predefined allocators appearing in a uses_allocators clause must
23372 // have traits specified.
23373 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23375 diag::err_omp_nonpredefined_allocator_without_traits);
23376 continue;
23377 }
23378 // No allocator traits - just convert it to rvalue.
23379 if (!D.AllocatorTraits)
23380 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
23381 DSAStack->addUsesAllocatorsDecl(
23382 DRE->getDecl(),
23383 IsPredefinedAllocator
23384 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23385 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23386 }
23387 Expr *AllocatorTraitsExpr = nullptr;
23388 if (D.AllocatorTraits) {
23390 AllocatorTraitsExpr = D.AllocatorTraits;
23391 } else {
23392 // OpenMP [2.12.5, target Construct]
23393 // Arrays that contain allocator traits that appear in a uses_allocators
23394 // clause must be constant arrays, have constant values and be defined
23395 // in the same scope as the construct in which the clause appears.
23396 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23397 // Check that traits expr is a constant array.
23398 QualType TraitTy;
23399 if (const ArrayType *Ty =
23400 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23401 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23402 TraitTy = ConstArrayTy->getElementType();
23403 if (TraitTy.isNull() ||
23405 DSAStack->getOMPAlloctraitT()) ||
23406 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23407 /*CompareUnqualified=*/true))) {
23409 diag::err_omp_expected_array_alloctraits)
23410 << AllocatorTraitsExpr->getType();
23411 continue;
23412 }
23413 // Do not map by default allocator traits if it is a standalone
23414 // variable.
23415 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23416 DSAStack->addUsesAllocatorsDecl(
23417 DRE->getDecl(),
23418 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23419 }
23420 }
23421 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23422 NewD.Allocator = AllocatorExpr;
23423 NewD.AllocatorTraits = AllocatorTraitsExpr;
23424 NewD.LParenLoc = D.LParenLoc;
23425 NewD.RParenLoc = D.RParenLoc;
23426 }
23427 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23428 NewData);
23429}
23430
23432 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23433 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23435 for (Expr *RefExpr : Locators) {
23436 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23437 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23438 // It will be analyzed later.
23439 Vars.push_back(RefExpr);
23440 continue;
23441 }
23442
23443 SourceLocation ELoc = RefExpr->getExprLoc();
23444 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23445
23446 if (!SimpleExpr->isLValue()) {
23447 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23448 << 1 << 0 << RefExpr->getSourceRange();
23449 continue;
23450 }
23451
23452 ExprResult Res;
23453 {
23454 Sema::TentativeAnalysisScope Trap(*this);
23455 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23456 }
23457 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
23458 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23459 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23460 << 1 << 0 << RefExpr->getSourceRange();
23461 continue;
23462 }
23463 Vars.push_back(SimpleExpr);
23464 }
23465
23466 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
23467 EndLoc, Modifier, Vars);
23468}
23469
23471 SourceLocation KindLoc,
23472 SourceLocation StartLoc,
23473 SourceLocation LParenLoc,
23474 SourceLocation EndLoc) {
23475 if (Kind == OMPC_BIND_unknown) {
23476 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23477 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23478 /*Last=*/unsigned(OMPC_BIND_unknown))
23479 << getOpenMPClauseName(OMPC_bind);
23480 return nullptr;
23481 }
23482
23483 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
23484 EndLoc);
23485}
Defines the clang::ASTContext interface.
#define V(N, I)
NodeId Parent
Definition ASTDiff.cpp:192
int Id
Definition ASTDiff.cpp:191
MatchType Type
StringRef P
auto * N
llvm::Error Error
llvm::Expected< T > Expected
static CompilationDatabasePluginRegistry::Add< FixedCompilationDatabasePlugin > X("fixed-compilation-database", "Reads plain-text flags file")
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
int Priority
Definition Format.cpp:2581
static const Decl * getCanonicalDecl(const Decl *D)
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition ParentMap.cpp:22
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
CastType
Definition SemaCast.cpp:46
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers=None, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude=llvm::None)
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
#define DSAStack
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file defines OpenMP AST classes for executable directives and clauses.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getV()
Get 'v' part of the associated expression/statement.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
Allows QualTypes to be sorted and hence used in maps and sets.
SourceLocation Begin
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
APSInt & getInt()
Definition APValue.h:415
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:209
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
DeclarationNameTable DeclarationNames
Definition ASTContext.h:663
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
void Deallocate(void *Ptr) const
Definition ASTContext.h:739
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
CanQualType DependentTy
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
IdentifierTable & Idents
Definition ASTContext.h:659
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false)
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType BoolTy
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element type.
CanQualType BoundMemberTy
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:772
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isInvalid() const
Definition Ownership.h:165
bool isUsable() const
Definition Ownership.h:166
PtrTy get() const
Definition Ownership.h:169
bool isUnset() const
Definition Ownership.h:167
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2645
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition Type.h:2955
QualType getElementType() const
Definition Type.h:2976
@ AS_Keyword
__ptr16, alignas(...), etc.
Represents an attribute applied to a statement.
Definition Stmt.h:1880
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition Stmt.cpp:423
SourceLocation getBeginLoc() const
Definition Stmt.h:1921
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3807
Expr * getLHS() const
Definition Expr.h:3856
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2087
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:3953
bool isRelationalOp() const
Definition Expr.h:3901
SourceLocation getOperatorLoc() const
Definition Expr.h:3848
SourceLocation getExprLoc() const
Definition Expr.h:3847
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:3925
Expr * getRHS() const
Definition Expr.h:3858
Opcode getOpcode() const
Definition Expr.h:3851
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2049
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a C++ constructor within a class.
Definition DeclCXX.h:2437
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2764
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:82
Represents a C++ struct/union/class.
Definition DeclCXX.h:254
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition DeclCXX.h:1188
bool hasDefinition() const
Definition DeclCXX.h:549
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:64
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition DeclSpec.h:197
SourceLocation getBeginLoc() const
Definition DeclSpec.h:73
bool isSet() const
Deprecated.
Definition DeclSpec.h:210
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition DeclSpec.cpp:151
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition DeclSpec.h:195
Represents the this expression in C++.
Definition ExprCXX.h:1142
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2801
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition Expr.cpp:1395
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.cpp:1537
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:2971
QualType withConst() const
Retrieves a version of this type with const applied.
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition Decl.h:4411
unsigned getNumParams() const
Definition Decl.h:4453
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5038
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:4455
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition Stmt.h:3545
This captures a statement into a function.
Definition Stmt.h:3532
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1399
SourceRange getSourceRange() const LLVM_READONLY
Definition Stmt.h:3732
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition Stmt.h:3633
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition Stmt.cpp:1423
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:3724
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3475
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition Type.h:2659
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1408
SourceLocation getBeginLoc() const
Definition Stmt.h:1535
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:381
ConditionalOperator - The ?: ternary operator.
Definition Expr.h:4145
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
Definition DeclBase.h:1323
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1378
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:1904
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition DeclBase.h:2028
bool isFileContext() const
Definition DeclBase.h:1974
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isNamespace() const
Definition DeclBase.h:1988
bool isTranslationUnit() const
Definition DeclBase.h:1979
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2159
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition DeclGroup.h:68
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1227
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.cpp:516
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:453
ValueDecl * getDecl()
Definition Expr.h:1295
SourceLocation getEndLoc() const LLVM_READONLY
Definition Expr.cpp:521
ConstexprSpecKind getConstexprSpecifier() const
Definition DeclSpec.h:755
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1299
const Decl * getSingleDecl() const
Definition Stmt.h:1314
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:83
T * getAttr() const
Definition DeclBase.h:545
bool hasAttrs() const
Definition DeclBase.h:491
void addAttr(Attr *A)
Definition DeclBase.cpp:887
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:565
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:132
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition DeclBase.cpp:459
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition DeclBase.cpp:469
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition DeclBase.h:938
bool isInvalidDecl() const
Definition DeclBase.h:560
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:531
void setAccess(AccessSpecifier AS)
Definition DeclBase.h:475
SourceLocation getLocation() const
Definition DeclBase.h:432
void setImplicit(bool I=true)
Definition DeclBase.h:566
void setReferenced(bool R=true)
Definition DeclBase.h:595
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1003
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition DeclBase.cpp:444
DeclContext * getDeclContext()
Definition DeclBase.h:441
AccessSpecifier getAccess() const
Definition DeclBase.h:480
AttrVec & getAttrs()
Definition DeclBase.h:497
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition DeclBase.cpp:328
bool hasAttr() const
Definition DeclBase.h:549
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:332
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:932
Kind getKind() const
Definition DeclBase.h:435
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:420
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition DeclSpec.h:1805
void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition DeclSpec.h:2231
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:1940
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2228
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclSpec.h:1976
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition DeclSpec.h:2613
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition DeclSpec.h:1955
IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2222
bool isInvalidType() const
Definition DeclSpec.h:2598
RAII object that enters a new expression evaluation context.
Definition Sema.h:13535
The return type of classify().
Definition Expr.h:323
This represents one expression.
Definition Expr.h:109
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isGLValue() const
Definition Expr.h:273
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition Expr.h:641
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:2958
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:168
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:430
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:185
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition Expr.h:232
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition Expr.cpp:2970
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:2953
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:2941
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition Expr.h:238
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:2949
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:270
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:437
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:214
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:2933
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:247
Optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr, bool isEvaluated=true) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition Expr.h:141
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Definition Decl.h:2873
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:2951
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3076
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition Expr.cpp:1001
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2566
Represents a function declaration or definition.
Definition Decl.h:1874
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2537
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2514
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2310
bool isConsteval() const
Definition Decl.h:2322
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3447
Represents a prototype with parameter type info, e.g.
Definition Type.h:3962
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition Stmt.h:1938
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition Expr.h:1718
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:1980
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition Overload.h:518
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:900
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition LangOptions.h:78
A class for iterating through a result set and possibly filtering out results.
Definition Lookup.h:643
Represents the results of name lookup.
Definition Lookup.h:46
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition Lookup.h:580
DeclClass * getAsSingle() const
Definition Lookup.h:533
bool empty() const
Return true if no decls were found.
Definition Lookup.h:339
Filter makeFilter()
Create a filter for this result set.
Definition Lookup.h:708
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition Lookup.h:543
bool isAmbiguous() const
Definition Lookup.h:301
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition Lookup.h:308
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition Lookup.h:550
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition Lookup.h:609
iterator end() const
Definition Lookup.h:336
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition Lookup.h:335
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3168
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3247
Expr * getBase() const
Definition Expr.h:3241
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
Definition Expr.h:3225
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3359
This represents a decl that may have a name.
Definition Decl.h:247
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:268
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:274
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:311
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition Decl.cpp:1751
A C++ nested-name-specifier augmented with source location information.
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the '#pragma omp ...' directive.
OpenMP 5.0 [2.1.5, Array Sections].
Definition ExprOpenMP.h:56
Expr * getLength()
Get length of array section.
Definition ExprOpenMP.h:102
SourceLocation getColonLocFirst() const
Definition ExprOpenMP.h:118
Expr * getBase()
An array section can be written only as Base[LowerBound:Length].
Definition ExprOpenMP.h:85
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:4799
Expr * getLowerBound()
Get lower bound of array section.
Definition ExprOpenMP.h:94
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
Definition ExprOpenMP.h:148
Expr * getBase()
Fetches base expression of array shaping expression.
Definition ExprOpenMP.h:214
This represents 'atomic_default_mem_order' clause in the '#pragma omp requires' directive.
This represents 'bind' clause in the '#pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
This represents 'capture' clause in the '#pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
Definition DeclOpenMP.h:383
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Class that represents a component of a mappable expression.
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'shedule', 'firstprivate' etc.
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
SourceLocation getEndLoc() const
Returns the ending location of the clause.
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
This represents 'collapse' clause in the '#pragma omp ...' directive.
This represents 'compare' clause in the '#pragma omp atomic' directive.
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents '#pragma omp declare mapper ...' directive.
Definition DeclOpenMP.h:287
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents '#pragma omp declare reduction ...' directive.
Definition DeclOpenMP.h:171
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the '#pragma omp ...' directive.
This represents 'defaultmap' clause in the '#pragma omp ...' directive.
This represents implicit clause 'depend' for the '#pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
This represents 'detach' clause in the '#pragma omp task' directive.
This represents 'device' clause in the '#pragma omp ...' directive.
This represents 'dist_schedule' clause in the '#pragma omp ...' directive.
This represents 'dynamic_allocators' clause in the '#pragma omp requires' directive.
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Representation of the 'full' clause of the '#pragma omp unroll' directive.
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
This represents 'grainsize' clause in the '#pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the '#pragma omp ...' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, ArrayRef< Expr * > PrefExprs, bool IsTarget, bool IsTargetSync, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the '#pragma omp ...' directives.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
This represents 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
This represents 'order' clause in the '#pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
Definition DeclOpenMP.h:416
clauselist_range clauselists()
Definition DeclOpenMP.h:441
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'reverse_offload' clause in the '#pragma omp requires' directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'schedule' clause in the '#pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
This represents the 'sizes' clause in the '#pragma omp tile' directive.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
unsigned getNumSizes() const
Returns the number of list items.
MutableArrayRef< Expr * > getSizesRefs()
Returns the tile size expressions.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'thread_limit' clause in the '#pragma omp ...' directive.
This represents '#pragma omp threadprivate ...' directive.
Definition DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threads' clause in the '#pragma omp ...' directive.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the '#pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the '#pragma omp requires' directive.
This represents 'untied' clause in the '#pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
SourceLocation getLParenLoc() const
Returns the location of '('.
This represents 'write' clause in the '#pragma omp atomic' directive.
Wrapper for void* pointer.
Definition Ownership.h:50
void * getAsOpaquePtr() const
Definition Ownership.h:90
PtrTy get() const
Definition Ownership.h:80
static OpaquePtr make(PtrTy P)
Definition Ownership.h:60
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1135
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1185
void setIsUnique(bool V)
Definition Expr.h:1187
Represents a parameter to a function.
Definition Decl.h:1680
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition Decl.cpp:2813
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
Definition Expr.cpp:4638
A (possibly-)qualified type.
Definition Type.h:731
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2468
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition Type.h:6634
QualType withRestrict() const
Definition Type.h:921
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3158
QualType withConst() const
Definition Type.h:905
void addConst()
Add the const type qualifier to this QualType.
Definition Type.h:902
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition Type.h:796
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition Type.h:6559
bool isConstant(const ASTContext &Ctx) const
Definition Type.h:866
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition Type.h:6755
QualType getCanonicalType() const
Definition Type.h:6598
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition Type.h:6639
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition Type.h:6726
const Type * getTypePtrOrNull() const
Definition Type.h:6563
Represents a struct/union/class.
Definition Decl.h:3919
field_range fields() const
Definition Decl.h:4145
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition Type.h:4706
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Base for LValueReferenceType and RValueReferenceType.
Definition Type.h:2823
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:40
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition Scope.h:354
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition Scope.h:279
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:244
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition Scope.h:488
A RAII object to enter scope of a compound statement.
Definition Sema.h:4905
Expr * get() const
Definition Sema.h:4862
A generic diagnostic builder for errors which may or may not be deferred.
Definition Sema.h:1733
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:9463
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:12516
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:355
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit=false)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:13365
const ValueDecl * getOpenMPDeclareMapperVarName() const
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false)
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:4165
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:4206
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:4208
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:4210
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPGrainsizeClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition Sema.cpp:1860
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:5030
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=llvm::None)
Called on well-formed 'to' clause.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4375
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition Sema.h:796
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
@ AR_inaccessible
Definition Sema.h:7600
PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP=nullptr, const Decl *D=nullptr, QualType BlockType=QualType())
Pop a function (or block or lambda or captured region) scope from the stack.
Definition Sema.cpp:2191
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
NamedDecl * HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists)
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:696
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt=None)
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
Definition SemaDecl.cpp:286
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
ASTContext & Context
Definition Sema.h:409
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
OMPClause * ActOnOpenMPMapClause(ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers=llvm::None)
Called on well-formed 'map' clause.
void ActOnCapturedRegionError()
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:57
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition SemaExpr.cpp:736
ASTContext & getASTContext() const
Definition Sema.h:1625
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=NotForRedeclaration)
Look up a name, looking for a single declaration.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, ArrayRef< Expr * > PrefExprs, bool IsTarget, bool IsTargetSync, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
void PopExpressionEvaluationContext()
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
@ None
This is not a defaultable comparison operator.
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:3179
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
void PushFunctionScope()
Enter a new function scope.
Definition Sema.cpp:2074
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
const LangOptions & getLangOpts() const
Definition Sema.h:1618
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext=nullptr, bool EnteringContext=false, const ObjCObjectPointerType *OPT=nullptr, bool RecordFailure=true)
Try to "correct" a typo in the source code by finding visible declarations whose names are similar to...
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
Preprocessor & PP
Definition Sema.h:408
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
void CheckExtraCXXDefaultArguments(Declarator &D)
CheckExtraCXXDefaultArguments - Check for any extra default arguments in the declarator,...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
const LangOptions & LangOpts
Definition Sema.h:407
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2303
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
DeclContext * getCurLexicalContext() const
Definition Sema.h:13376
OMPClause * ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition Sema.h:10943
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1950
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
ExprResult DefaultLvalueConversion(Expr *E)
Definition SemaExpr.cpp:626
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:2317
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition Sema.cpp:2260
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:421
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
@ TryCapture_ExplicitByVal
Definition Sema.h:5295
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
@ AA_Initializing
Definition Sema.h:3610
@ AA_Converting
Definition Sema.h:3609
@ AA_Casting
Definition Sema.h:3612
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input)
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
bool areMultiversionVariantFunctionsCompatible(const FunctionDecl *OldFD, const FunctionDecl *NewFD, const PartialDiagnostic &NoProtoDiagID, const PartialDiagnosticAt &NoteCausedDiagIDAt, const PartialDiagnosticAt &NoSupportDiagIDAt, const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, bool ConstexprSupported, bool CLinkageMayDiffer)
Checks if the variant/multiversion functions are compatible.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
Definition Sema.h:10981
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
Definition Sema.h:2428
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
@ CTK_ErrorRecovery
Definition Sema.h:4403
@ Private
The private module fragment, between 'module :private;' and the end of the translation unit.
Definition Sema.h:1908
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPDeclareVariantAttr::InteropType > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2245
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
OMPClause * ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
Optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
OMPClause * ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:73
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition Sema.h:1124
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
void DiscardCleanupsInEvaluationContext()
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
RedeclarationKind forRedeclarationInCurContext()
Definition Sema.h:4228
ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose=true)
DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
Definition SemaExpr.cpp:502
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
void PopDeclContext()
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace)
Filters out lookup results that don't fall within the given scope as determined by isDeclInScope.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp tile' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
void ActOnUninitializedDecl(Decl *dcl)
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=llvm::None)
Called on well-formed 'from' clause.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=llvm::None)
Called on well-formed 'reduction' clause.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false)
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
Definition Sema.cpp:1440
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
void EndOpenMPClause()
End analysis of clauses.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
TypeSourceInfo * GetTypeForDeclarator(Declarator &D, Scope *S)
GetTypeForDeclarator - Convert the type for the specified declarator to Type instances.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=llvm::None)
Called on well-formed 'task_reduction' clause.
sema::FunctionScopeInfo * getEnclosingFunction() const
Definition Sema.cpp:2275
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition Sema.cpp:2639
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr)
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition SemaStmt.cpp:409
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
FullExprArg MakeFullExpr(Expr *Arg)
Definition Sema.h:4878
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=llvm::None)
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD=nullptr)
Definition Sema.cpp:1844
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:6719
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:70
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:348
child_range children()
Definition Stmt.cpp:285
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:324
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition Stmt.cpp:195
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:336
bool isTLSSupported() const
Whether the target supports thread-local storage.
bool isVLASupported() const
Whether target supports variable-length arrays.
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition Decl.h:3176
A container of type source information.
Definition Type.h:6530
QualType getType() const
Return the type wrapped by this type source info.
Definition Type.h:6541
The base class of the type hierarchy.
Definition Type.h:1556
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.cpp:1759
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition Type.cpp:1898
bool isArrayType() const
Definition Type.h:6873
bool isArithmeticType() const
Definition Type.cpp:2152
bool isPointerType() const
Definition Type.h:6807
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition Type.h:7128
const T * castAs() const
Member-template castAs<specific type>.
Definition Type.h:7369
bool isReferenceType() const
Definition Type.h:6819
bool isEnumeralType() const
Definition Type.h:6901
bool isScalarType() const
Definition Type.h:7183
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:625
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2108
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition Type.h:2252
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition Type.h:7065
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition Type.h:2244
bool isAnyComplexType() const
Definition Type.h:6905
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition Type.h:1947
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2058
bool isFunctionProtoType() const
Definition Type.h:2088
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition Type.h:7225
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition Type.h:2262
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition Type.h:7355
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2234
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition Type.h:7319
bool isFunctionType() const
Definition Type.h:6803
bool isStructureOrClassType() const
Definition Type.cpp:581
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2137
bool isFloatingType() const
Definition Type.cpp:2121
bool isAnyPointerType() const
Definition Type.h:6811
const T * getAs() const
Member-template getAs<specific type>'.
Definition Type.h:7302
bool isRecordType() const
Definition Type.h:6897
bool isUnionType() const
Definition Type.cpp:595
bool isFunctionNoProtoType() const
Definition Type.h:2087
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2165
Expr * getSubExpr() const
Definition Expr.h:2210
Opcode getOpcode() const
Definition Expr.h:2205
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End)
Definition ExprCXX.cpp:369
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:674
void setType(QualType newType)
Definition Decl.h:686
QualType getType() const
Definition Decl.h:685
Represents a variable declaration or definition.
Definition Decl.h:874
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2058
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition Decl.h:1182
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1477
TLSKind getTLSKind() const
Definition Decl.cpp:2075
bool hasInit() const
Definition Decl.cpp:2306
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1360
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition Decl.h:1374
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2168
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2097
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2165
@ CInit
C-style initialization with assignment.
Definition Decl.h:879
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:882
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1198
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1141
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1123
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition Decl.h:1257
const Expr * getInit() const
Definition Decl.h:1283
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1099
@ TLS_None
Not a TLS variable.
Definition Decl.h:891
void setInit(Expr *I)
Definition Decl.cpp:2362
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1210
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1168
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition Decl.h:1379
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1144
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1083
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
Definition Decl.cpp:2408
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition Decl.h:1177
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1273
Directive - Abstract class representing a parsed verify directive.
Retains information about a captured region.
Definition ScopeInfo.h:779
Retains information about a function, method, or block that is currently being parsed.
Definition ScopeInfo.h:102
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound stamement scopes in the function.
Definition ScopeInfo.h:219
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
unsigned long uint64_t
Defines the clang::TargetInfo interface.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
Definition Interp.h:239
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
Definition Address.h:177
@ CPlusPlus
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition Specifiers.h:134
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:136
Expr * AssertSuccess(ExprResult R)
Definition Ownership.h:292
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ OMPC_REDUCTION_unknown
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition OpenMPKinds.h:38
@ OMPC_SCHEDULE_MODIFIER_last
Definition OpenMPKinds.h:43
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition OpenMPKinds.h:39
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
@ CR_Default
@ CR_OpenMP
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition Specifiers.h:241
@ SC_Register
Definition Specifiers.h:242
@ SC_None
Definition Specifiers.h:235
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
Expr * Cond
};
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition Decl.h:4727
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
Definition OpenMPKinds.h:87
ExprResult ExprEmpty()
Definition Ownership.h:289
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ C
Languages that the frontend can parse and compile.
StmtResult StmtError()
Definition Ownership.h:279
@ SD_Static
Static storage duration.
Definition Specifiers.h:312
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
@ OMPC_BIND_unknown
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition OpenMPKinds.h:54
@ OMPC_DEPEND_unknown
Definition OpenMPKinds.h:58
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
ExprResult ExprError()
Definition Ownership.h:278
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
Definition OpenMPKinds.h:99
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition OpenMPKinds.h:91
@ OMPC_MOTION_MODIFIER_unknown
Definition OpenMPKinds.h:95
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition OpenMPKinds.h:62
@ OMPC_LINEAR_unknown
Definition OpenMPKinds.h:66
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition OpenMPKinds.h:24
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition Specifiers.h:117
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:120
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:124
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
Definition Address.h:174
@ None
The alignment was not explicit in code.
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
Definition OpenMPKinds.h:47
@ OMPC_DEVICE_unknown
Definition OpenMPKinds.h:50
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition OpenMPKinds.h:78
@ OMPC_MAP_MODIFIER_unknown
Definition OpenMPKinds.h:79
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition OpenMPKinds.h:27
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
ActionResult< Expr * > ExprResult
Definition Ownership.h:262
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ OMPC_ORDER_unknown
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition OpenMPKinds.h:30
@ OMPC_SCHEDULE_unknown
Definition OpenMPKinds.h:34
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:108
@ AS_public
Definition Specifiers.h:109
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition OpenMPKinds.h:70
@ OMPC_MAP_unknown
Definition OpenMPKinds.h:74
#define true
Definition stdbool.h:21
#define false
Definition stdbool.h:22
#define bool
Definition stdbool.h:20
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
const Expr * RHS
The original right-hand side.
Definition ExprCXX.h:311
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition ExprCXX.h:307
const Expr * LHS
The original left-hand side.
Definition ExprCXX.h:309
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:612
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:614
Extra information about a function prototype.
Definition Type.h:4039
SourceLocation OmpAllMemoryLoc
Location of 'omp_all_memory'.
SourceLocation ColonLoc
Colon location.
OpenMPDependClauseKind DepKind
Dependency type (one of in, out, inout).
SourceLocation DepLoc
Dependency type location.
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
Data used for processing a list of variables in OpenMP clauses.
Definition Sema.h:11611
CXXScopeSpec ReductionOrMapperIdScopeSpec
Definition Sema.h:11615
SmallVector< OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers > MapTypeModifiers
Definition Sema.h:11620
SmallVector< OpenMPMotionModifierKind, NumberOfOMPMotionModifiers > MotionModifiers
Definition Sema.h:11624
SourceLocation ExtraModifierLoc
Definition Sema.h:11627
DeclarationNameInfo ReductionOrMapperId
Definition Sema.h:11616
SmallVector< SourceLocation, NumberOfOMPMotionModifiers > MotionModifiersLoc
Definition Sema.h:11625
SourceLocation OmpAllMemoryLoc
Definition Sema.h:11628
SmallVector< SourceLocation, NumberOfOMPMapClauseModifiers > MapTypeModifiersLoc
Definition Sema.h:11622
int ExtraModifier
Additional modifier for linear, map, depend or lastprivate clause.
Definition Sema.h:11617
Data for list of allocators.
Definition Sema.h:11804
Expr * Allocator
Allocator.
Definition Sema.h:11806
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Definition Sema.h:11810
Expr * AllocatorTraits
Allocator traits.
Definition Sema.h:11808
Clang specific specialization of the OMPContext to lookup target features.